More updates to types
Project: http://git-wip-us.apache.org/repos/asf/incubator-quickstep/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-quickstep/commit/9cb664c8 Tree: http://git-wip-us.apache.org/repos/asf/incubator-quickstep/tree/9cb664c8 Diff: http://git-wip-us.apache.org/repos/asf/incubator-quickstep/diff/9cb664c8 Branch: refs/heads/refactor-type Commit: 9cb664c802f2a85862dea1cc41a08c989dd579e7 Parents: 0957264 Author: Jianqiao Zhu <[email protected]> Authored: Wed Oct 4 03:21:44 2017 -0500 Committer: Jianqiao Zhu <[email protected]> Committed: Wed Oct 11 13:37:54 2017 -0500 ---------------------------------------------------------------------- parser/ParseDataType.cpp | 6 +- parser/ParseDataType.hpp | 12 ++-- query_optimizer/resolver/Resolver.cpp | 108 ++++++++++++++++++++++++----- query_optimizer/resolver/Resolver.hpp | 3 + types/ArrayType.cpp | 7 ++ types/ArrayType.hpp | 10 ++- types/GenericValue.hpp | 35 +++++++--- types/TypeFactory-decl.hpp | 12 ++++ types/TypeFactory.cpp | 45 ++++++++++-- types/TypeSynthesizer.hpp | 6 ++ 10 files changed, 197 insertions(+), 47 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/9cb664c8/parser/ParseDataType.cpp ---------------------------------------------------------------------- diff --git a/parser/ParseDataType.cpp b/parser/ParseDataType.cpp index b960961..7892122 100644 --- a/parser/ParseDataType.cpp +++ b/parser/ParseDataType.cpp @@ -33,11 +33,11 @@ void ParseDataType::getFieldStringItems( std::vector<const ParseTreeNode*> *non_container_child_fields, std::vector<std::string> *container_child_field_names, std::vector<std::vector<const ParseTreeNode*>> *container_child_fields) const { - inline_field_names->emplace_back("name"); - inline_field_values->emplace_back(name_->value()); + inline_field_names->emplace_back("type_name"); + inline_field_values->emplace_back(type_name_->value()); inline_field_names->emplace_back("nullable"); - + inline_field_values->emplace_back(nullable_ ? "true" : "false"); container_child_field_names->emplace_back("parameters"); container_child_fields->emplace_back(); http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/9cb664c8/parser/ParseDataType.hpp ---------------------------------------------------------------------- diff --git a/parser/ParseDataType.hpp b/parser/ParseDataType.hpp index 96b7b96..b554011 100644 --- a/parser/ParseDataType.hpp +++ b/parser/ParseDataType.hpp @@ -41,7 +41,7 @@ class Type; class ParseDataTypeParameter : public ParseTreeNode { public: - enum class ParameterType { + enum ParameterType { kDataType, kLiteralValue }; @@ -64,15 +64,19 @@ class ParseDataType : public ParseTreeNode { public: ParseDataType(const int line_number, const int column_number, - ParseString *name) + ParseString *type_name) : ParseTreeNode(line_number, column_number), - name_(name), + type_name_(type_name), nullable_(false) {} std::string getName() const override { return "DataType"; } + const ParseString& type_name() const { + return *type_name_; + } + const std::vector<std::unique_ptr<ParseDataTypeParameter>>& parameters() const { return parameters_; } @@ -99,7 +103,7 @@ class ParseDataType : public ParseTreeNode { std::vector<std::vector<const ParseTreeNode*>> *container_child_fields) const override; private: - const std::unique_ptr<ParseString> name_; + const std::unique_ptr<ParseString> type_name_; std::vector<std::unique_ptr<ParseDataTypeParameter>> parameters_; bool nullable_; http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/9cb664c8/query_optimizer/resolver/Resolver.cpp ---------------------------------------------------------------------- diff --git a/query_optimizer/resolver/Resolver.cpp b/query_optimizer/resolver/Resolver.cpp index 694d741..8c77403 100644 --- a/query_optimizer/resolver/Resolver.cpp +++ b/query_optimizer/resolver/Resolver.cpp @@ -43,6 +43,7 @@ #include "parser/ParseBasicExpressions.hpp" #include "parser/ParseBlockProperties.hpp" #include "parser/ParseCaseExpressions.hpp" +#include "parser/ParseDataType.hpp" #include "parser/ParseExpression.hpp" #include "parser/ParseGeneratorTableReference.hpp" #include "parser/ParseGroupBy.hpp" @@ -118,6 +119,7 @@ #include "types/ArrayType.hpp" #include "types/GenericValue.hpp" #include "types/IntType.hpp" +#include "types/LongType.hpp" #include "types/MetaType.hpp" #include "types/NullType.hpp" #include "types/Type.hpp" @@ -639,14 +641,13 @@ L::LogicalPtr Resolver::resolveCreateTable( << "Column " << attribute_definition.name()->value() << " is specified more than once"; } - LOG(FATAL) << "TODO(refactor-type): To implement"; -// attributes.emplace_back( -// E::AttributeReference::Create(context_->nextExprId(), -// attribute_definition.name()->value(), -// attribute_definition.name()->value(), -// relation_name, -// attribute_definition.data_type().getType(), -// E::AttributeReferenceScope::kLocal)); + attributes.emplace_back( + E::AttributeReference::Create(context_->nextExprId(), + attribute_definition.name()->value(), + attribute_definition.name()->value(), + relation_name, + resolveDataType(attribute_definition.data_type()), + E::AttributeReferenceScope::kLocal)); attribute_name_set.insert(lower_attribute_name); } @@ -1120,7 +1121,7 @@ L::LogicalPtr Resolver::resolveInsertTuple( } // Create a NULL value. resolved_column_values.push_back(E::ScalarLiteral::Create( - GenericValue(relation_attributes[aid]->getValueType()))); + GenericValue::CreateNullValue(relation_attributes[aid]->getValueType()))); ++aid; } @@ -1196,6 +1197,72 @@ L::LogicalPtr Resolver::resolveUpdate( resolved_where_predicate); } +const Type& Resolver::resolveDataType(const ParseDataType &parse_data_type) { + const std::string &type_name = ToLower(parse_data_type.type_name().value()); + if (!TypeFactory::TypeNameIsValid(type_name)) { + THROW_SQL_ERROR_AT(&parse_data_type.type_name()) + << "Unrecognized type name: " << type_name; + } + + const TypeID type_id = TypeFactory::GetTypeIDForName(type_name); + const MemoryLayout memory_layout = TypeUtil::GetMemoryLayout(type_id); + + const auto &parse_parameters = parse_data_type.parameters(); + if (memory_layout == kCxxInlinePod) { + if (!parse_parameters.empty()) { + THROW_SQL_ERROR_AT(parse_parameters.front()) + << "Invalid parameter to type " << type_name; + } + return TypeFactory::GetType(type_id, parse_data_type.nullable()); + } + + std::vector<GenericValue> values; + for (const auto ¶m : parse_parameters) { + if (param->getParameterType() == ParseDataTypeParameter::kLiteralValue) { + const ParseLiteralValue &literal_value = + static_cast<const ParseDataTypeParameterLiteralValue&>(*param).literal_value(); + const Type *value_type = nullptr; + TypedValue value = literal_value.concretize(nullptr, &value_type); + DCHECK(value_type != nullptr); + values.emplace_back(GenericValue::CreateWithTypedValue(*value_type, value)); + } else { + DCHECK(param->getParameterType() == ParseDataTypeParameter::kDataType); + const ParseDataType &element_type = + static_cast<const ParseDataTypeParameterDataType&>(*param).data_type(); + values.emplace_back( + GenericValue::CreateWithLiteral(MetaType::InstanceNonNullable(), + &resolveDataType(element_type))); + } + } + + if (memory_layout == kParInlinePod || memory_layout == kParOutOfLinePod) { + if (values.size() != 1) { + THROW_SQL_ERROR_AT(parse_parameters.front()) + << "Invalid parameter to type " << type_name; + } + const GenericValue &value = values.front(); + const Type &value_type = value.getType(); + + std::size_t length = 0; + if (value_type.getTypeID() == kInt) { + length = value.getLiteral<kInt>(); + } else if (value_type.getTypeID() == kLong) { + length = value.getLiteral<kLong>(); + } else { + THROW_SQL_ERROR_AT(parse_parameters.front()) + << "Invalid parameter to type " << type_name; + } + return TypeFactory::GetType(type_id, length); + } + + DCHECK(memory_layout == kCxxGeneric); + if (!TypeFactory::TypeParametersAreValid(type_id, values)) { + THROW_SQL_ERROR_AT(parse_parameters.front()) + << "Invalid parameter to type " << type_name; + } + return TypeFactory::GetType(type_id, values); +} + L::LogicalPtr Resolver::resolveSelect( const ParseSelect &select_query, const std::string &select_name, @@ -2455,7 +2522,8 @@ E::ScalarPtr Resolver::resolveExpression( const Type *concrete_type = nullptr; TypedValue concrete = parse_literal_scalar.literal_value() ->concretize(type_hint, &concrete_type); - return E::ScalarLiteral::Create(GenericValue(*concrete_type, concrete)); + return E::ScalarLiteral::Create( + GenericValue::CreateWithTypedValue(*concrete_type, concrete)); } case ParseExpression::kSearchedCaseExpression: { const ParseSearchedCaseExpression &parse_searched_case_expression = @@ -2499,11 +2567,13 @@ E::ScalarPtr Resolver::resolveArray( const auto &parse_elements = parse_array.elements(); if (parse_elements.empty()) { // TODO(jianqiao): Figure out how to handle empty array. - const GenericValue meta_null_type_value( - MetaType::InstanceNonNullable(), &NullType::InstanceNullable()); + const GenericValue meta_null_type_value = + GenericValue::CreateWithLiteral(MetaType::InstanceNonNullable(), + &NullType::InstanceNullable()); return E::ScalarLiteral::Create( - GenericValue(ArrayType::InstanceNonNullable({meta_null_type_value}), - ArrayLiteral())); + GenericValue::CreateWithLiteral( + ArrayType::InstanceNonNullable({meta_null_type_value}), + ArrayLiteral())); } else { // Currently we only support homogeneous array with literal values. std::vector<E::ScalarLiteralPtr> literals; @@ -2533,8 +2603,9 @@ E::ScalarPtr Resolver::resolveArray( } DCHECK(element_type != nullptr); - const GenericValue meta_element_type_value( - MetaType::InstanceNonNullable(), element_type); + const GenericValue meta_element_type_value = + GenericValue::CreateWithLiteral(MetaType::InstanceNonNullable(), + element_type); const Type &array_type = ArrayType::InstanceNonNullable({meta_element_type_value}); @@ -2544,9 +2615,8 @@ E::ScalarPtr Resolver::resolveArray( array_literal->emplace_back( element_type->cloneValue(literal->value().getValue())); } - return E::ScalarLiteral::Create(GenericValue(array_type, - array_literal.release(), - true /* take_ownership */)); + return E::ScalarLiteral::Create( + GenericValue::CreateWithOwnedData(array_type, array_literal.release())); } } http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/9cb664c8/query_optimizer/resolver/Resolver.hpp ---------------------------------------------------------------------- diff --git a/query_optimizer/resolver/Resolver.hpp b/query_optimizer/resolver/Resolver.hpp index c44d8ef..1844493 100644 --- a/query_optimizer/resolver/Resolver.hpp +++ b/query_optimizer/resolver/Resolver.hpp @@ -42,6 +42,7 @@ class CatalogDatabase; class CatalogRelation; class Comparison; class ParseArray; +class ParseDataType; class ParseExpression; class ParseFunctionCall; class ParseGeneratorTableReference; @@ -581,6 +582,8 @@ class Resolver { */ const CatalogRelation *resolveRelationName(const ParseString *relation_name); + const Type& resolveDataType(const ParseDataType &parse_data_type); + /** * @brief Determines whether \p op can apply to \p left_operand and \p * right_operand. http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/9cb664c8/types/ArrayType.cpp ---------------------------------------------------------------------- diff --git a/types/ArrayType.cpp b/types/ArrayType.cpp index 30cc4a5..765a1a0 100644 --- a/types/ArrayType.cpp +++ b/types/ArrayType.cpp @@ -39,6 +39,13 @@ std::string ArrayType::getName() const { return name; } +bool ArrayType::TypeParametersAreValid(const std::vector<GenericValue> ¶meters) { + if (parameters.size() != 1u) { + return false; + } + return parameters.front().getType().getTypeID() == kMetaType; +} + bool ArrayType::checkValuesEqual(const UntypedLiteral *lhs, const UntypedLiteral *rhs, const Type &rhs_type) const { http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/9cb664c8/types/ArrayType.hpp ---------------------------------------------------------------------- diff --git a/types/ArrayType.hpp b/types/ArrayType.hpp index f7e2212..5eaff92 100644 --- a/types/ArrayType.hpp +++ b/types/ArrayType.hpp @@ -63,19 +63,17 @@ class ArrayType : public TypeSynthesizer<kArray> { return false; } + static bool TypeParametersAreValid(const std::vector<GenericValue> ¶meters); + private: ArrayType(const bool nullable, const std::vector<GenericValue> ¶meters) : TypeSynthesizer<kArray>(nullable, 0, 0x1000, parameters), element_type_(ExtractType(parameters)) { - // TODO(refactor-type): Possibly infinite maximum size. - // TODO(refactor-type): Validate parameters. } static const Type& ExtractType(const std::vector<GenericValue> ¶meters) { - DCHECK_EQ(1u, parameters.size()); - const GenericValue &value = parameters.front(); - DCHECK(value.getType().getTypeID() == kMetaType); - return **static_cast<const MetaTypeLiteral*>(value.getValue()); + DCHECK(TypeParametersAreValid(parameters)); + return **static_cast<const MetaTypeLiteral*>(parameters.front().getValue()); } const Type &element_type_; http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/9cb664c8/types/GenericValue.hpp ---------------------------------------------------------------------- diff --git a/types/GenericValue.hpp b/types/GenericValue.hpp index 62dd9a3..3e8045b 100644 --- a/types/GenericValue.hpp +++ b/types/GenericValue.hpp @@ -43,20 +43,30 @@ namespace quickstep { class GenericValue { public: - GenericValue(const Type &type) - : type_(type), value_(nullptr), owns_(true) {} + static GenericValue CreateNullValue(const Type &type) { + return GenericValue(type, nullptr, true); + } - GenericValue(const Type &type, - const UntypedLiteral *value, - const bool take_ownership) - : type_(type), value_(value), owns_(take_ownership) {} + static GenericValue CreateWithOwnedData(const Type &type, + const UntypedLiteral *value) { + return GenericValue(type, value, true); + } - GenericValue(const Type &type, const TypedValue &value) - : type_(type), value_(type.unmarshallTypedValue(value)), owns_(true) {} + static GenericValue CreateReference(const Type &type, + const UntypedLiteral *value) { + return GenericValue(type, value, false); + } + + static GenericValue CreateWithTypedValue(const Type &type, + const TypedValue &value) { + return GenericValue(type, type.unmarshallTypedValue(value), true); + } template <typename TypeClass> - GenericValue(const TypeClass &type, const typename TypeClass::cpptype &value) - : type_(type), value_(type.cloneValue(&value)), owns_(true) {} + static GenericValue CreateWithLiteral(const TypeClass &type, + const typename TypeClass::cpptype &value) { + return GenericValue(type, type.cloneValue(&value), true); + } GenericValue(const GenericValue &other) : type_(other.type_), @@ -153,6 +163,11 @@ class GenericValue { } private: + GenericValue(const Type &type, + const UntypedLiteral *value, + const bool take_ownership) + : type_(type), value_(value), owns_(take_ownership) {} + const Type &type_; const UntypedLiteral *value_; bool owns_; http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/9cb664c8/types/TypeFactory-decl.hpp ---------------------------------------------------------------------- diff --git a/types/TypeFactory-decl.hpp b/types/TypeFactory-decl.hpp index 6edc05b..f67208e 100644 --- a/types/TypeFactory-decl.hpp +++ b/types/TypeFactory-decl.hpp @@ -21,6 +21,9 @@ #define QUICKSTEP_TYPES_TYPE_FACTORY_DECL_HPP_ #include <cstddef> +#include <string> +#include <unordered_map> +#include <vector> #include "types/GenericValue.hpp" #include "types/TypeID.hpp" @@ -42,6 +45,10 @@ namespace serialization { class Type; } **/ class TypeFactory { public: + static bool TypeNameIsValid(const std::string &type_name); + + static TypeID GetTypeIDForName(const std::string &type_name); + /** * @brief Determine if a length parameter is required when getting a Type of * the specified TypeID. @@ -51,6 +58,9 @@ class TypeFactory { **/ static bool TypeRequiresLengthParameter(const TypeID id); + static bool TypeParametersAreValid(const TypeID id, + const std::vector<GenericValue> ¶meters); + /** * @brief Factory method to get a Type by its TypeID. * @note This version is for Types without a length parameter (currently @@ -131,6 +141,8 @@ class TypeFactory { // instantiated. TypeFactory(); + static const std::unordered_map<std::string, TypeID>& GetTypeNameMap(); + DISALLOW_COPY_AND_ASSIGN(TypeFactory); }; http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/9cb664c8/types/TypeFactory.cpp ---------------------------------------------------------------------- diff --git a/types/TypeFactory.cpp b/types/TypeFactory.cpp index 45202f1..9029408 100644 --- a/types/TypeFactory.cpp +++ b/types/TypeFactory.cpp @@ -21,6 +21,7 @@ #include <cstddef> #include <string> +#include <unordered_map> #include <vector> #include "types/GenericValue.hpp" @@ -30,15 +31,41 @@ #include "types/TypeSynthesizer.hpp" #include "types/TypeUtil.hpp" #include "utility/Macros.hpp" +#include "utility/StringUtil.hpp" #include "glog/logging.h" namespace quickstep { +bool TypeFactory::TypeNameIsValid(const std::string &type_name) { + const auto &type_name_map = GetTypeNameMap(); + return type_name_map.find(type_name) != type_name_map.end(); +} + +TypeID TypeFactory::GetTypeIDForName(const std::string &type_name) { + DCHECK(TypeNameIsValid(type_name)); + return GetTypeNameMap().at(type_name); +} + bool TypeFactory::TypeRequiresLengthParameter(const TypeID id) { return TypeUtil::IsParameterizedPod(id); } +bool TypeFactory::TypeParametersAreValid( + const TypeID id, const std::vector<GenericValue> ¶meters) { + if (TypeUtil::GetMemoryLayout(id) != kCxxGeneric) { + return false; + } + + return InvokeOnTypeID<TypeIDSelectorMemoryLayout<kCxxGeneric>>( + id, + [&](auto id) -> bool { // NOLINT(build/c++11) + using TypeClass = typename TypeIDTrait<decltype(id)::value>::TypeClass; + return TypeClass::TypeParametersAreValid(parameters); + }); +} + + const Type& TypeFactory::GetType(const TypeID id, const bool nullable) { DCHECK(TypeUtil::GetMemoryLayout(id) == kCxxInlinePod) @@ -124,12 +151,10 @@ GenericValue TypeFactory::ReconstructValueFromProto( const serialization::GenericValue &proto) { const Type &type = ReconstructFromProto(proto.type()); if (proto.has_data()) { - return GenericValue(type, - type.unmarshallValue(proto.data().c_str(), - proto.data().size()), - true /* take_ownership */); + return GenericValue::CreateWithOwnedData( + type, type.unmarshallValue(proto.data().c_str(), proto.data().size())); } else { - return GenericValue(type); + return GenericValue::CreateNullValue(type); } } @@ -168,4 +193,14 @@ const Type* TypeFactory::GetUnifyingType(const Type &first, const Type &second) return unifier; } +const std::unordered_map<std::string, TypeID>& TypeFactory::GetTypeNameMap() { + static std::unordered_map<std::string, TypeID> type_name_map; + if (type_name_map.empty()) { + for (std::size_t i = 0; i < static_cast<std::size_t>(kNumTypeIDs); ++i) { + type_name_map.emplace(ToLower(kTypeNames[i]), static_cast<TypeID>(i)); + } + } + return type_name_map; +} + } // namespace quickstep http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/9cb664c8/types/TypeSynthesizer.hpp ---------------------------------------------------------------------- diff --git a/types/TypeSynthesizer.hpp b/types/TypeSynthesizer.hpp index f0761d1..0b5842f 100644 --- a/types/TypeSynthesizer.hpp +++ b/types/TypeSynthesizer.hpp @@ -365,6 +365,12 @@ class TypeSynthesizePolicy< // LOG(FATAL) << "Not implemented"; // } + template <typename T = TypeClass> + static bool TypeParametersAreValid(const std::vector<GenericValue> ¶meters, + decltype(new T(true)) * = 0) { + return parameters.empty(); + } + protected: TypeSynthesizePolicy(const bool nullable, const std::size_t minimum_byte_length,
