mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-22 15:42:02 +00:00
156 lines
4.5 KiB
C++
156 lines
4.5 KiB
C++
#include <base/map.h>
|
|
#include <Common/StringUtils.h>
|
|
#include <Columns/ColumnMap.h>
|
|
#include <Core/Field.h>
|
|
#include <DataTypes/DataTypeMap.h>
|
|
#include <DataTypes/DataTypeArray.h>
|
|
#include <DataTypes/DataTypeTuple.h>
|
|
#include <DataTypes/DataTypeLowCardinality.h>
|
|
#include <DataTypes/DataTypeFactory.h>
|
|
#include <DataTypes/Serializations/SerializationMap.h>
|
|
#include <Parsers/IAST.h>
|
|
#include <IO/WriteBufferFromString.h>
|
|
#include <IO/Operators.h>
|
|
|
|
|
|
namespace DB
|
|
{
|
|
|
|
namespace ErrorCodes
|
|
{
|
|
extern const int NUMBER_OF_ARGUMENTS_DOESNT_MATCH;
|
|
extern const int BAD_ARGUMENTS;
|
|
}
|
|
|
|
DataTypeMap::DataTypeMap(const DataTypePtr & nested_)
|
|
: nested(nested_)
|
|
{
|
|
const auto * type_array = typeid_cast<const DataTypeArray *>(nested.get());
|
|
if (!type_array)
|
|
throw Exception(ErrorCodes::BAD_ARGUMENTS,
|
|
"Expected Array(Tuple(key, value)) type, got {}", nested->getName());
|
|
|
|
const auto * type_tuple = typeid_cast<const DataTypeTuple *>(type_array->getNestedType().get());
|
|
if (!type_tuple)
|
|
throw Exception(ErrorCodes::BAD_ARGUMENTS,
|
|
"Expected Array(Tuple(key, value)) type, got {}", nested->getName());
|
|
|
|
if (type_tuple->getElements().size() != 2)
|
|
throw Exception(ErrorCodes::BAD_ARGUMENTS,
|
|
"Expected Array(Tuple(key, value)) type, got {}", nested->getName());
|
|
|
|
key_type = type_tuple->getElement(0);
|
|
value_type = type_tuple->getElement(1);
|
|
assertKeyType();
|
|
}
|
|
|
|
DataTypeMap::DataTypeMap(const DataTypes & elems_)
|
|
{
|
|
assert(elems_.size() == 2);
|
|
key_type = elems_[0];
|
|
value_type = elems_[1];
|
|
|
|
assertKeyType();
|
|
|
|
nested = std::make_shared<DataTypeArray>(
|
|
std::make_shared<DataTypeTuple>(DataTypes{key_type, value_type}, Names{"keys", "values"}));
|
|
}
|
|
|
|
DataTypeMap::DataTypeMap(const DataTypePtr & key_type_, const DataTypePtr & value_type_)
|
|
: key_type(key_type_), value_type(value_type_)
|
|
, nested(std::make_shared<DataTypeArray>(
|
|
std::make_shared<DataTypeTuple>(DataTypes{key_type_, value_type_}, Names{"keys", "values"})))
|
|
{
|
|
assertKeyType();
|
|
}
|
|
|
|
void DataTypeMap::assertKeyType() const
|
|
{
|
|
if (!isValidKeyType(key_type))
|
|
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Map cannot have a key of type {}", key_type->getName());
|
|
}
|
|
|
|
|
|
std::string DataTypeMap::doGetName() const
|
|
{
|
|
WriteBufferFromOwnString s;
|
|
s << "Map(" << key_type->getName() << ", " << value_type->getName() << ")";
|
|
|
|
return s.str();
|
|
}
|
|
|
|
std::string DataTypeMap::doGetPrettyName(size_t indent) const
|
|
{
|
|
WriteBufferFromOwnString s;
|
|
s << "Map(" << key_type->getPrettyName(indent) << ", " << value_type->getPrettyName(indent) << ')';
|
|
return s.str();
|
|
}
|
|
|
|
MutableColumnPtr DataTypeMap::createColumn() const
|
|
{
|
|
return ColumnMap::create(nested->createColumn());
|
|
}
|
|
|
|
Field DataTypeMap::getDefault() const
|
|
{
|
|
return Map();
|
|
}
|
|
|
|
SerializationPtr DataTypeMap::doGetDefaultSerialization() const
|
|
{
|
|
return std::make_shared<SerializationMap>(
|
|
key_type->getDefaultSerialization(),
|
|
value_type->getDefaultSerialization(),
|
|
nested->getDefaultSerialization());
|
|
}
|
|
|
|
bool DataTypeMap::equals(const IDataType & rhs) const
|
|
{
|
|
if (typeid(rhs) != typeid(*this))
|
|
return false;
|
|
|
|
const DataTypeMap & rhs_map = static_cast<const DataTypeMap &>(rhs);
|
|
return nested->equals(*rhs_map.nested);
|
|
}
|
|
|
|
bool DataTypeMap::isValidKeyType(DataTypePtr key_type)
|
|
{
|
|
return !isNullableOrLowCardinalityNullable(key_type);
|
|
}
|
|
|
|
DataTypePtr DataTypeMap::getNestedTypeWithUnnamedTuple() const
|
|
{
|
|
const auto & from_array = assert_cast<const DataTypeArray &>(*nested);
|
|
const auto & from_tuple = assert_cast<const DataTypeTuple &>(*from_array.getNestedType());
|
|
return std::make_shared<DataTypeArray>(std::make_shared<DataTypeTuple>(from_tuple.getElements()));
|
|
}
|
|
|
|
void DataTypeMap::forEachChild(const DB::IDataType::ChildCallback & callback) const
|
|
{
|
|
callback(*key_type);
|
|
key_type->forEachChild(callback);
|
|
callback(*value_type);
|
|
value_type->forEachChild(callback);
|
|
}
|
|
|
|
static DataTypePtr create(const ASTPtr & arguments)
|
|
{
|
|
if (!arguments || arguments->children.size() != 2)
|
|
throw Exception(ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH, "Map data type family must have two arguments: key and value types");
|
|
|
|
DataTypes nested_types;
|
|
nested_types.reserve(arguments->children.size());
|
|
|
|
for (const ASTPtr & child : arguments->children)
|
|
nested_types.emplace_back(DataTypeFactory::instance().get(child));
|
|
|
|
return std::make_shared<DataTypeMap>(nested_types);
|
|
}
|
|
|
|
|
|
void registerDataTypeMap(DataTypeFactory & factory)
|
|
{
|
|
factory.registerDataType("Map", create);
|
|
}
|
|
}
|