2016-07-05 16:23:37 +00:00
|
|
|
#include <DB/DataTypes/DataTypeNullable.h>
|
|
|
|
#include <DB/Columns/ColumnNullable.h>
|
|
|
|
#include <DB/Common/typeid_cast.h>
|
2016-07-11 14:54:46 +00:00
|
|
|
#include <DB/DataTypes/NullSymbol.h>
|
2016-07-05 16:23:37 +00:00
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
2016-07-11 16:41:57 +00:00
|
|
|
namespace
|
|
|
|
{
|
|
|
|
|
|
|
|
inline bool isNullValue(const NullValuesByteMap * null_map, size_t row_num) const
|
|
|
|
{
|
|
|
|
return (null_map != nullptr) && ((*null_map)[row_num] == 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2016-07-07 10:33:12 +00:00
|
|
|
DataTypeNullable::DataTypeNullable(DataTypePtr nested_data_type_)
|
|
|
|
: nested_data_type{nested_data_type_}
|
2016-07-05 16:23:37 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string DataTypeNullable::getName() const
|
|
|
|
{
|
2016-07-07 10:33:12 +00:00
|
|
|
return "Nullable(" + nested_data_type.get()->getName() + ")";
|
2016-07-05 16:23:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool DataTypeNullable::isNullable() const
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool DataTypeNullable::isNumeric() const
|
|
|
|
{
|
2016-07-07 10:33:12 +00:00
|
|
|
return nested_data_type.get()->isNumeric();
|
2016-07-05 16:23:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool DataTypeNullable::behavesAsNumber() const
|
|
|
|
{
|
2016-07-07 10:33:12 +00:00
|
|
|
return nested_data_type.get()->behavesAsNumber();
|
2016-07-05 16:23:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
DataTypePtr DataTypeNullable::clone() const
|
|
|
|
{
|
2016-07-07 10:33:12 +00:00
|
|
|
return std::make_shared<DataTypeNullable>(nested_data_type.get()->clone());
|
2016-07-05 16:23:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void DataTypeNullable::serializeBinary(const IColumn & column, WriteBuffer & ostr, size_t offset, size_t limit) const
|
|
|
|
{
|
|
|
|
const ColumnNullable * col = typeid_cast<const ColumnNullable *>(&column);
|
|
|
|
if (col == nullptr)
|
|
|
|
throw Exception{"Discrepancy between data type and column type", ErrorCodes::LOGICAL_ERROR};
|
|
|
|
|
2016-07-07 10:33:12 +00:00
|
|
|
nested_data_type.get()->serializeBinary(*(col->getNestedColumn().get()), ostr, offset, limit);
|
2016-07-05 16:23:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void DataTypeNullable::deserializeBinary(IColumn & column, ReadBuffer & istr, size_t limit, double avg_value_size_hint) const
|
|
|
|
{
|
|
|
|
ColumnNullable * col = typeid_cast<ColumnNullable *>(&column);
|
|
|
|
if (col == nullptr)
|
|
|
|
throw Exception{"Discrepancy between data type and column type", ErrorCodes::LOGICAL_ERROR};
|
|
|
|
|
2016-07-07 10:33:12 +00:00
|
|
|
nested_data_type.get()->deserializeBinary(*(col->getNestedColumn().get()), istr, limit, avg_value_size_hint);
|
2016-07-05 16:23:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void DataTypeNullable::serializeBinary(const Field & field, WriteBuffer & ostr) const
|
|
|
|
{
|
2016-07-07 10:33:12 +00:00
|
|
|
nested_data_type.get()->serializeBinary(field, ostr);
|
2016-07-05 16:23:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void DataTypeNullable::deserializeBinary(Field & field, ReadBuffer & istr) const
|
|
|
|
{
|
2016-07-07 10:33:12 +00:00
|
|
|
nested_data_type.get()->deserializeBinary(field, istr);
|
2016-07-05 16:23:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void DataTypeNullable::serializeBinary(const IColumn & column, size_t row_num, WriteBuffer & ostr) const
|
|
|
|
{
|
|
|
|
const ColumnNullable * col = typeid_cast<const ColumnNullable *>(&column);
|
|
|
|
if (col == nullptr)
|
|
|
|
throw Exception{"Discrepancy between data type and column type", ErrorCodes::LOGICAL_ERROR};
|
|
|
|
|
2016-07-07 10:33:12 +00:00
|
|
|
nested_data_type.get()->serializeBinary(*(col->getNestedColumn().get()), row_num, ostr);
|
2016-07-05 16:23:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void DataTypeNullable::deserializeBinary(IColumn & column, ReadBuffer & istr) const
|
|
|
|
{
|
|
|
|
ColumnNullable * col = typeid_cast<ColumnNullable *>(&column);
|
|
|
|
if (col == nullptr)
|
|
|
|
throw Exception{"Discrepancy between data type and column type", ErrorCodes::LOGICAL_ERROR};
|
|
|
|
|
2016-07-07 10:33:12 +00:00
|
|
|
nested_data_type.get()->deserializeBinary(*(col->getNestedColumn().get()), istr);
|
2016-07-05 16:23:37 +00:00
|
|
|
}
|
|
|
|
|
2016-07-11 14:54:46 +00:00
|
|
|
void DataTypeNullable::serializeTextEscaped(const IColumn & column, size_t row_num, WriteBuffer & ostr) const
|
2016-07-05 16:23:37 +00:00
|
|
|
{
|
|
|
|
const ColumnNullable * col = typeid_cast<const ColumnNullable *>(&column);
|
|
|
|
if (col == nullptr)
|
|
|
|
throw Exception{"Discrepancy between data type and column type", ErrorCodes::LOGICAL_ERROR};
|
|
|
|
|
|
|
|
const ColumnUInt8 & content = static_cast<const ColumnUInt8 &>(*(col->getNullValuesByteMap().get()));
|
2016-07-11 14:54:46 +00:00
|
|
|
const auto & null_map = content.getData();
|
|
|
|
|
|
|
|
if (isNullValue(&null_map, row_num))
|
|
|
|
writeCString(NullSymbol::Plain::name, ostr);
|
|
|
|
else
|
|
|
|
nested_data_type.get()->serializeTextEscaped(*(col->getNestedColumn().get()), row_num, ostr);
|
2016-07-05 16:23:37 +00:00
|
|
|
}
|
|
|
|
|
2016-07-11 14:54:46 +00:00
|
|
|
void DataTypeNullable::deserializeTextEscaped(IColumn & column, ReadBuffer & istr) const
|
2016-07-05 16:23:37 +00:00
|
|
|
{
|
|
|
|
ColumnNullable * col = typeid_cast<ColumnNullable *>(&column);
|
|
|
|
if (col == nullptr)
|
|
|
|
throw Exception{"Discrepancy between data type and column type", ErrorCodes::LOGICAL_ERROR};
|
|
|
|
|
|
|
|
ColumnUInt8 & content = static_cast<ColumnUInt8 &>(*(col->getNullValuesByteMap().get()));
|
2016-07-11 14:54:46 +00:00
|
|
|
auto & null_map = content.getData();
|
|
|
|
|
|
|
|
if (NullSymbol::Deserializer<NullSymbol::Escaped>::execute(column, istr, &null_map))
|
|
|
|
col->insertDefault();
|
|
|
|
else
|
|
|
|
nested_data_type.get()->deserializeTextEscaped(*(col->getNestedColumn().get()), istr);
|
2016-07-05 16:23:37 +00:00
|
|
|
}
|
|
|
|
|
2016-07-11 14:54:46 +00:00
|
|
|
void DataTypeNullable::serializeTextQuoted(const IColumn & column, size_t row_num, WriteBuffer & ostr) const
|
2016-07-05 16:23:37 +00:00
|
|
|
{
|
|
|
|
const ColumnNullable * col = typeid_cast<const ColumnNullable *>(&column);
|
|
|
|
if (col == nullptr)
|
|
|
|
throw Exception{"Discrepancy between data type and column type", ErrorCodes::LOGICAL_ERROR};
|
|
|
|
|
|
|
|
const ColumnUInt8 & content = static_cast<const ColumnUInt8 &>(*(col->getNullValuesByteMap().get()));
|
2016-07-11 14:54:46 +00:00
|
|
|
const auto & null_map = content.getData();
|
|
|
|
|
|
|
|
if (isNullValue(&null_map, row_num))
|
|
|
|
writeCString(NullSymbol::Quoted::name, ostr);
|
|
|
|
else
|
|
|
|
nested_data_type.get()->serializeTextQuoted(*(col->getNestedColumn().get()), row_num, ostr);
|
2016-07-05 16:23:37 +00:00
|
|
|
}
|
|
|
|
|
2016-07-11 14:54:46 +00:00
|
|
|
void DataTypeNullable::deserializeTextQuoted(IColumn & column, ReadBuffer & istr) const
|
2016-07-05 16:23:37 +00:00
|
|
|
{
|
|
|
|
ColumnNullable * col = typeid_cast<ColumnNullable *>(&column);
|
|
|
|
if (col == nullptr)
|
|
|
|
throw Exception{"Discrepancy between data type and column type", ErrorCodes::LOGICAL_ERROR};
|
|
|
|
|
|
|
|
ColumnUInt8 & content = static_cast<ColumnUInt8 &>(*(col->getNullValuesByteMap().get()));
|
2016-07-11 14:54:46 +00:00
|
|
|
auto & null_map = content.getData();
|
|
|
|
|
|
|
|
if (NullSymbol::Deserializer<NullSymbol::Quoted>::execute(column, istr, &null_map))
|
|
|
|
col->insertDefault();
|
|
|
|
else
|
|
|
|
nested_data_type.get()->deserializeTextQuoted(*(col->getNestedColumn().get()), istr);
|
2016-07-05 16:23:37 +00:00
|
|
|
}
|
|
|
|
|
2016-07-11 16:37:44 +00:00
|
|
|
void DataTypeNullable::serializeTextCSV(const IColumn & column, size_t row_num, WriteBuffer & ostr) const
|
2016-07-05 16:23:37 +00:00
|
|
|
{
|
|
|
|
const ColumnNullable * col = typeid_cast<const ColumnNullable *>(&column);
|
|
|
|
if (col == nullptr)
|
|
|
|
throw Exception{"Discrepancy between data type and column type", ErrorCodes::LOGICAL_ERROR};
|
|
|
|
|
|
|
|
const ColumnUInt8 & content = static_cast<const ColumnUInt8 &>(*(col->getNullValuesByteMap().get()));
|
2016-07-11 16:37:44 +00:00
|
|
|
const auto & null_map = content.getData();
|
|
|
|
|
|
|
|
if (isNullValue(&null_map, row_num))
|
|
|
|
writeCString(NullSymbol::Quoted::name, ostr);
|
|
|
|
else
|
|
|
|
nested_data_type.get()->serializeTextCSV(*(col->getNestedColumn().get()), row_num, ostr);
|
2016-07-05 16:23:37 +00:00
|
|
|
}
|
|
|
|
|
2016-07-11 16:37:44 +00:00
|
|
|
void DataTypeNullable::deserializeTextCSV(IColumn & column, ReadBuffer & istr, const char delimiter) const
|
2016-07-05 16:23:37 +00:00
|
|
|
{
|
|
|
|
ColumnNullable * col = typeid_cast<ColumnNullable *>(&column);
|
|
|
|
if (col == nullptr)
|
|
|
|
throw Exception{"Discrepancy between data type and column type", ErrorCodes::LOGICAL_ERROR};
|
|
|
|
|
|
|
|
ColumnUInt8 & content = static_cast<ColumnUInt8 &>(*(col->getNullValuesByteMap().get()));
|
2016-07-11 16:37:44 +00:00
|
|
|
auto & null_map = content.getData();
|
|
|
|
|
|
|
|
if (NullSymbol::Deserializer<NullSymbol::Quoted>::execute(column, istr, &null_map))
|
|
|
|
col->insertDefault();
|
|
|
|
else
|
|
|
|
nested_data_type.get()->deserializeTextCSV(*(col->getNestedColumn().get()), istr, delimiter);
|
2016-07-05 16:23:37 +00:00
|
|
|
}
|
|
|
|
|
2016-07-11 14:54:46 +00:00
|
|
|
void DataTypeNullable::serializeText(const IColumn & column, size_t row_num, WriteBuffer & ostr) const
|
2016-07-05 16:23:37 +00:00
|
|
|
{
|
|
|
|
const ColumnNullable * col = typeid_cast<const ColumnNullable *>(&column);
|
|
|
|
if (col == nullptr)
|
|
|
|
throw Exception{"Discrepancy between data type and column type", ErrorCodes::LOGICAL_ERROR};
|
|
|
|
|
|
|
|
const ColumnUInt8 & content = static_cast<const ColumnUInt8 &>(*(col->getNullValuesByteMap().get()));
|
2016-07-11 14:54:46 +00:00
|
|
|
const auto & null_map = content.getData();
|
|
|
|
|
|
|
|
if (isNullValue(&null_map, row_num))
|
|
|
|
writeCString(NullSymbol::Plain::name, ostr);
|
|
|
|
else
|
|
|
|
nested_data_type.get()->serializeText(*(col->getNestedColumn().get()), row_num, ostr);
|
2016-07-05 16:23:37 +00:00
|
|
|
}
|
|
|
|
|
2016-07-11 16:37:44 +00:00
|
|
|
void DataTypeNullable::serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr) const
|
2016-07-05 16:23:37 +00:00
|
|
|
{
|
|
|
|
const ColumnNullable * col = typeid_cast<const ColumnNullable *>(&column);
|
|
|
|
if (col == nullptr)
|
|
|
|
throw Exception{"Discrepancy between data type and column type", ErrorCodes::LOGICAL_ERROR};
|
|
|
|
|
|
|
|
const ColumnUInt8 & content = static_cast<const ColumnUInt8 &>(*(col->getNullValuesByteMap().get()));
|
2016-07-11 16:37:44 +00:00
|
|
|
const auto & null_map = content.getData();
|
|
|
|
|
|
|
|
if (isNullValue(&null_map, row_num))
|
|
|
|
writeCString(NullSymbol::JSON::name, ostr);
|
|
|
|
else
|
|
|
|
nested_data_type.get()->serializeTextJSON(*(col->getNestedColumn().get()), row_num, ostr);
|
2016-07-05 16:23:37 +00:00
|
|
|
}
|
|
|
|
|
2016-07-11 16:37:44 +00:00
|
|
|
void DataTypeNullable::deserializeTextJSON(IColumn & column, ReadBuffer & istr) const
|
2016-07-05 16:23:37 +00:00
|
|
|
{
|
|
|
|
ColumnNullable * col = typeid_cast<ColumnNullable *>(&column);
|
|
|
|
if (col == nullptr)
|
|
|
|
throw Exception{"Discrepancy between data type and column type", ErrorCodes::LOGICAL_ERROR};
|
|
|
|
|
|
|
|
ColumnUInt8 & content = static_cast<ColumnUInt8 &>(*(col->getNullValuesByteMap().get()));
|
2016-07-11 16:37:44 +00:00
|
|
|
auto & null_map = content.getData();
|
|
|
|
|
|
|
|
if (NullSymbol::Deserializer<NullSymbol::JSON>::execute(column, istr, &null_map))
|
|
|
|
col->insertDefault();
|
|
|
|
else
|
|
|
|
nested_data_type.get()->deserializeTextJSON(*(col->getNestedColumn().get()), istr);
|
2016-07-05 16:23:37 +00:00
|
|
|
}
|
|
|
|
|
2016-07-11 14:54:46 +00:00
|
|
|
void DataTypeNullable::serializeTextXML(const IColumn & column, size_t row_num, WriteBuffer & ostr) const
|
2016-07-05 16:23:37 +00:00
|
|
|
{
|
|
|
|
const ColumnNullable * col = typeid_cast<const ColumnNullable *>(&column);
|
|
|
|
if (col == nullptr)
|
|
|
|
throw Exception{"Discrepancy between data type and column type", ErrorCodes::LOGICAL_ERROR};
|
|
|
|
|
|
|
|
const ColumnUInt8 & content = static_cast<const ColumnUInt8 &>(*(col->getNullValuesByteMap().get()));
|
2016-07-11 14:54:46 +00:00
|
|
|
auto & null_map = content.getData();
|
|
|
|
|
|
|
|
if (isNullValue(&null_map, row_num))
|
|
|
|
writeCString(NullSymbol::XML::name, ostr);
|
|
|
|
else
|
|
|
|
nested_data_type.get()->serializeTextXML(*(col->getNestedColumn().get()), row_num, ostr);
|
2016-07-05 16:23:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ColumnPtr DataTypeNullable::createColumn() const
|
|
|
|
{
|
2016-07-07 10:33:12 +00:00
|
|
|
return std::make_shared<ColumnNullable>(nested_data_type.get()->createColumn());
|
2016-07-05 16:23:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ColumnPtr DataTypeNullable::createConstColumn(size_t size, const Field & field) const
|
|
|
|
{
|
2016-07-07 10:33:12 +00:00
|
|
|
return std::make_shared<ColumnNullable>(nested_data_type.get()->createConstColumn(size, field));
|
2016-07-05 16:23:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Field DataTypeNullable::getDefault() const
|
|
|
|
{
|
2016-07-07 10:33:12 +00:00
|
|
|
return nested_data_type.get()->getDefault();
|
2016-07-05 16:23:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
size_t DataTypeNullable::getSizeOfField() const
|
|
|
|
{
|
2016-07-07 10:33:12 +00:00
|
|
|
return nested_data_type.get()->getSizeOfField();
|
2016-07-05 16:23:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
DataTypePtr & DataTypeNullable::getNestedType()
|
|
|
|
{
|
2016-07-07 10:33:12 +00:00
|
|
|
return nested_data_type;
|
2016-07-05 16:23:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const DataTypePtr & DataTypeNullable::getNestedType() const
|
|
|
|
{
|
2016-07-07 10:33:12 +00:00
|
|
|
return nested_data_type;
|
2016-07-05 16:23:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|