2017-04-01 09:19:00 +00:00
|
|
|
#include <Columns/ColumnFixedString.h>
|
|
|
|
#include <Columns/ColumnConst.h>
|
2011-08-07 02:08:22 +00:00
|
|
|
|
2018-06-10 19:22:49 +00:00
|
|
|
#include <Formats/FormatSettings.h>
|
2017-04-01 09:19:00 +00:00
|
|
|
#include <DataTypes/DataTypeFixedString.h>
|
2017-07-16 03:05:40 +00:00
|
|
|
#include <DataTypes/DataTypeFactory.h>
|
2011-08-07 02:08:22 +00:00
|
|
|
|
2019-02-10 17:12:22 +00:00
|
|
|
#include <IO/WriteBuffer.h>
|
2017-04-01 09:19:00 +00:00
|
|
|
#include <IO/ReadHelpers.h>
|
|
|
|
#include <IO/WriteHelpers.h>
|
|
|
|
#include <IO/VarInt.h>
|
2011-08-07 02:08:22 +00:00
|
|
|
|
2017-07-16 03:05:40 +00:00
|
|
|
#include <Parsers/IAST.h>
|
|
|
|
#include <Parsers/ASTLiteral.h>
|
|
|
|
|
2017-07-13 20:58:19 +00:00
|
|
|
#include <Common/typeid_cast.h>
|
2019-08-21 02:28:04 +00:00
|
|
|
#include <Common/assert_cast.h>
|
2011-08-07 02:08:22 +00:00
|
|
|
|
2017-07-16 03:05:40 +00:00
|
|
|
|
2011-08-07 02:08:22 +00:00
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
2016-01-11 21:46:36 +00:00
|
|
|
namespace ErrorCodes
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
extern const int CANNOT_READ_ALL_DATA;
|
2017-07-16 03:05:40 +00:00
|
|
|
extern const int NUMBER_OF_ARGUMENTS_DOESNT_MATCH;
|
|
|
|
extern const int UNEXPECTED_AST_STRUCTURE;
|
2016-01-11 21:46:36 +00:00
|
|
|
}
|
|
|
|
|
2011-08-07 02:08:22 +00:00
|
|
|
|
2018-12-13 13:41:47 +00:00
|
|
|
std::string DataTypeFixedString::doGetName() const
|
2015-10-12 07:05:54 +00:00
|
|
|
{
|
2020-03-10 18:16:14 +00:00
|
|
|
return "FixedString(" + toString(n) + ")";
|
2015-10-12 07:05:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-08-07 02:08:22 +00:00
|
|
|
void DataTypeFixedString::serializeBinary(const Field & field, WriteBuffer & ostr) const
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
const String & s = get<const String &>(field);
|
|
|
|
ostr.write(s.data(), std::min(s.size(), n));
|
|
|
|
if (s.size() < n)
|
|
|
|
for (size_t i = s.size(); i < n; ++i)
|
|
|
|
ostr.write(0);
|
2011-08-07 02:08:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DataTypeFixedString::deserializeBinary(Field & field, ReadBuffer & istr) const
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
field = String();
|
|
|
|
String & s = get<String &>(field);
|
|
|
|
s.resize(n);
|
2018-09-02 03:00:04 +00:00
|
|
|
istr.readStrict(s.data(), n);
|
2011-08-07 02:08:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-02-16 16:39:39 +00:00
|
|
|
void DataTypeFixedString::serializeBinary(const IColumn & column, size_t row_num, WriteBuffer & ostr) const
|
|
|
|
{
|
2019-08-21 02:28:04 +00:00
|
|
|
ostr.write(reinterpret_cast<const char *>(&assert_cast<const ColumnFixedString &>(column).getChars()[n * row_num]), n);
|
2016-02-16 16:39:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DataTypeFixedString::deserializeBinary(IColumn & column, ReadBuffer & istr) const
|
|
|
|
{
|
2019-08-21 02:28:04 +00:00
|
|
|
ColumnFixedString::Chars & data = assert_cast<ColumnFixedString &>(column).getChars();
|
2017-04-01 07:20:54 +00:00
|
|
|
size_t old_size = data.size();
|
|
|
|
data.resize(old_size + n);
|
|
|
|
try
|
|
|
|
{
|
2019-03-07 20:04:59 +00:00
|
|
|
istr.readStrict(reinterpret_cast<char *>(data.data() + old_size), n);
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
|
|
|
catch (...)
|
|
|
|
{
|
|
|
|
data.resize_assume_reserved(old_size);
|
|
|
|
throw;
|
|
|
|
}
|
2016-02-16 16:39:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-02-19 00:41:24 +00:00
|
|
|
void DataTypeFixedString::serializeBinaryBulk(const IColumn & column, WriteBuffer & ostr, size_t offset, size_t limit) const
|
2011-08-07 02:08:22 +00:00
|
|
|
{
|
2018-11-25 00:08:50 +00:00
|
|
|
const ColumnFixedString::Chars & data = typeid_cast<const ColumnFixedString &>(column).getChars();
|
2011-08-07 02:08:22 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
size_t size = data.size() / n;
|
2012-07-18 18:27:42 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
if (limit == 0 || offset + limit > size)
|
|
|
|
limit = size - offset;
|
2012-07-18 18:27:42 +00:00
|
|
|
|
2018-09-02 04:36:32 +00:00
|
|
|
if (limit)
|
|
|
|
ostr.write(reinterpret_cast<const char *>(&data[n * offset]), n * limit);
|
2011-08-07 02:08:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-02-19 00:41:24 +00:00
|
|
|
void DataTypeFixedString::deserializeBinaryBulk(IColumn & column, ReadBuffer & istr, size_t limit, double /*avg_value_size_hint*/) const
|
2011-08-07 02:08:22 +00:00
|
|
|
{
|
2018-11-25 00:08:50 +00:00
|
|
|
ColumnFixedString::Chars & data = typeid_cast<ColumnFixedString &>(column).getChars();
|
2011-08-07 02:08:22 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
size_t initial_size = data.size();
|
|
|
|
size_t max_bytes = limit * n;
|
|
|
|
data.resize(initial_size + max_bytes);
|
|
|
|
size_t read_bytes = istr.readBig(reinterpret_cast<char *>(&data[initial_size]), max_bytes);
|
2011-08-07 02:08:22 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
if (read_bytes % n != 0)
|
2018-07-13 14:42:30 +00:00
|
|
|
throw Exception("Cannot read all data of type FixedString. Bytes read:" + toString(read_bytes) + ". String size:" + toString(n) + ".",
|
2017-04-01 07:20:54 +00:00
|
|
|
ErrorCodes::CANNOT_READ_ALL_DATA);
|
2012-07-18 19:16:16 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
data.resize(initial_size + read_bytes);
|
2011-08-07 02:08:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-06-05 21:39:01 +00:00
|
|
|
void DataTypeFixedString::serializeText(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings &) const
|
2011-08-07 02:08:22 +00:00
|
|
|
{
|
2019-08-21 02:28:04 +00:00
|
|
|
writeString(reinterpret_cast<const char *>(&assert_cast<const ColumnFixedString &>(column).getChars()[n * row_num]), n, ostr);
|
2011-08-07 02:08:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-06-05 21:39:01 +00:00
|
|
|
void DataTypeFixedString::serializeTextEscaped(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings &) const
|
2011-08-07 02:08:22 +00:00
|
|
|
{
|
2019-08-21 02:28:04 +00:00
|
|
|
const char * pos = reinterpret_cast<const char *>(&assert_cast<const ColumnFixedString &>(column).getChars()[n * row_num]);
|
2017-04-01 07:20:54 +00:00
|
|
|
writeAnyEscapedString<'\''>(pos, pos + n, ostr);
|
2011-08-07 02:08:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-02-19 20:01:31 +00:00
|
|
|
static inline void alignStringLength(const DataTypeFixedString & type,
|
|
|
|
ColumnFixedString::Chars & data,
|
|
|
|
size_t string_start)
|
|
|
|
{
|
2021-01-11 01:50:30 +00:00
|
|
|
ColumnFixedString::alignStringLength(data, type.getN(), string_start);
|
2019-02-19 20:01:31 +00:00
|
|
|
}
|
|
|
|
|
2016-02-16 16:39:39 +00:00
|
|
|
template <typename Reader>
|
|
|
|
static inline void read(const DataTypeFixedString & self, IColumn & column, Reader && reader)
|
2011-08-07 02:08:22 +00:00
|
|
|
{
|
2018-11-25 00:08:50 +00:00
|
|
|
ColumnFixedString::Chars & data = typeid_cast<ColumnFixedString &>(column).getChars();
|
2017-04-01 07:20:54 +00:00
|
|
|
size_t prev_size = data.size();
|
|
|
|
try
|
|
|
|
{
|
|
|
|
reader(data);
|
2019-02-19 20:01:31 +00:00
|
|
|
alignStringLength(self, data, prev_size);
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
|
|
|
catch (...)
|
|
|
|
{
|
|
|
|
data.resize_assume_reserved(prev_size);
|
|
|
|
throw;
|
|
|
|
}
|
2011-08-07 02:08:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-06-05 21:39:01 +00:00
|
|
|
void DataTypeFixedString::deserializeTextEscaped(IColumn & column, ReadBuffer & istr, const FormatSettings &) const
|
2011-08-07 02:08:22 +00:00
|
|
|
{
|
2018-11-25 00:08:50 +00:00
|
|
|
read(*this, column, [&istr](ColumnFixedString::Chars & data) { readEscapedStringInto(data, istr); });
|
2011-08-07 02:08:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-06-05 21:39:01 +00:00
|
|
|
void DataTypeFixedString::serializeTextQuoted(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings &) const
|
2011-08-07 02:08:22 +00:00
|
|
|
{
|
2019-08-21 02:28:04 +00:00
|
|
|
const char * pos = reinterpret_cast<const char *>(&assert_cast<const ColumnFixedString &>(column).getChars()[n * row_num]);
|
2017-04-01 07:20:54 +00:00
|
|
|
writeAnyQuotedString<'\''>(pos, pos + n, ostr);
|
2011-08-07 02:08:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-06-05 21:39:01 +00:00
|
|
|
void DataTypeFixedString::deserializeTextQuoted(IColumn & column, ReadBuffer & istr, const FormatSettings &) const
|
2011-08-07 02:08:22 +00:00
|
|
|
{
|
2018-11-25 00:08:50 +00:00
|
|
|
read(*this, column, [&istr](ColumnFixedString::Chars & data) { readQuotedStringInto<true>(data, istr); });
|
2011-08-07 02:08:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-05-18 21:07:23 +00:00
|
|
|
void DataTypeFixedString::deserializeWholeText(IColumn & column, ReadBuffer & istr, const FormatSettings &) const
|
|
|
|
{
|
|
|
|
read(*this, column, [&istr](ColumnFixedString::Chars & data) { readStringInto(data, istr); });
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-08-06 10:02:26 +00:00
|
|
|
void DataTypeFixedString::serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings & settings) const
|
2013-05-16 12:52:09 +00:00
|
|
|
{
|
2019-08-21 02:28:04 +00:00
|
|
|
const char * pos = reinterpret_cast<const char *>(&assert_cast<const ColumnFixedString &>(column).getChars()[n * row_num]);
|
2018-08-06 10:02:26 +00:00
|
|
|
writeJSONString(pos, pos + n, ostr, settings);
|
2013-05-16 12:52:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-06-05 21:39:01 +00:00
|
|
|
void DataTypeFixedString::deserializeTextJSON(IColumn & column, ReadBuffer & istr, const FormatSettings &) const
|
2016-02-18 11:44:50 +00:00
|
|
|
{
|
2018-11-25 00:08:50 +00:00
|
|
|
read(*this, column, [&istr](ColumnFixedString::Chars & data) { readJSONStringInto(data, istr); });
|
2016-02-18 11:44:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-06-08 01:51:55 +00:00
|
|
|
void DataTypeFixedString::serializeTextXML(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings &) const
|
2016-02-14 02:37:42 +00:00
|
|
|
{
|
2019-08-21 02:28:04 +00:00
|
|
|
const char * pos = reinterpret_cast<const char *>(&assert_cast<const ColumnFixedString &>(column).getChars()[n * row_num]);
|
2020-12-02 09:00:27 +00:00
|
|
|
writeXMLStringForTextElement(pos, pos + n, ostr);
|
2016-02-14 02:37:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-06-05 21:39:01 +00:00
|
|
|
void DataTypeFixedString::serializeTextCSV(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings &) const
|
2016-02-07 08:42:21 +00:00
|
|
|
{
|
2019-08-21 02:28:04 +00:00
|
|
|
const char * pos = reinterpret_cast<const char *>(&assert_cast<const ColumnFixedString &>(column).getChars()[n * row_num]);
|
2017-04-01 07:20:54 +00:00
|
|
|
writeCSVString(pos, pos + n, ostr);
|
2016-02-07 08:42:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-06-05 21:39:01 +00:00
|
|
|
void DataTypeFixedString::deserializeTextCSV(IColumn & column, ReadBuffer & istr, const FormatSettings & settings) const
|
2016-02-07 08:42:21 +00:00
|
|
|
{
|
2018-11-25 00:08:50 +00:00
|
|
|
read(*this, column, [&istr, &csv = settings.csv](ColumnFixedString::Chars & data) { readCSVStringInto(data, istr, csv); });
|
2016-02-07 08:42:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-14 03:56:56 +00:00
|
|
|
MutableColumnPtr DataTypeFixedString::createColumn() const
|
2011-08-07 02:08:22 +00:00
|
|
|
{
|
2017-12-14 01:43:19 +00:00
|
|
|
return ColumnFixedString::create(n);
|
2011-08-07 02:08:22 +00:00
|
|
|
}
|
|
|
|
|
2019-10-04 17:46:36 +00:00
|
|
|
Field DataTypeFixedString::getDefault() const
|
|
|
|
{
|
|
|
|
return String();
|
|
|
|
}
|
2011-08-12 18:27:39 +00:00
|
|
|
|
2017-12-23 01:05:29 +00:00
|
|
|
bool DataTypeFixedString::equals(const IDataType & rhs) const
|
|
|
|
{
|
|
|
|
return typeid(rhs) == typeid(*this) && n == static_cast<const DataTypeFixedString &>(rhs).n;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-03-10 18:16:14 +00:00
|
|
|
static DataTypePtr create(const ASTPtr & arguments)
|
2017-07-16 03:05:40 +00:00
|
|
|
{
|
2017-12-22 03:55:49 +00:00
|
|
|
if (!arguments || arguments->children.size() != 1)
|
2017-07-16 03:05:40 +00:00
|
|
|
throw Exception("FixedString data type family must have exactly one argument - size in bytes", ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
|
|
|
|
|
2019-03-11 13:22:51 +00:00
|
|
|
const auto * argument = arguments->children[0]->as<ASTLiteral>();
|
2017-07-16 03:05:40 +00:00
|
|
|
if (!argument || argument->value.getType() != Field::Types::UInt64 || argument->value.get<UInt64>() == 0)
|
|
|
|
throw Exception("FixedString data type family must have a number (positive integer) as its argument", ErrorCodes::UNEXPECTED_AST_STRUCTURE);
|
|
|
|
|
2020-03-10 18:16:14 +00:00
|
|
|
return std::make_shared<DataTypeFixedString>(argument->value.get<UInt64>());
|
2017-07-16 03:05:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void registerDataTypeFixedString(DataTypeFactory & factory)
|
|
|
|
{
|
|
|
|
factory.registerDataType("FixedString", create);
|
2017-12-28 04:28:05 +00:00
|
|
|
|
|
|
|
/// Compatibility alias.
|
2018-07-23 16:10:57 +00:00
|
|
|
factory.registerAlias("BINARY", "FixedString", DataTypeFactory::CaseInsensitive);
|
2017-07-16 03:05:40 +00:00
|
|
|
}
|
|
|
|
|
2011-08-07 02:08:22 +00:00
|
|
|
}
|