2016-02-14 02:37:42 +00:00
|
|
|
#include <DB/Columns/ColumnTuple.h>
|
|
|
|
#include <DB/Columns/ColumnConst.h>
|
|
|
|
#include <DB/DataStreams/NativeBlockInputStream.h>
|
|
|
|
#include <DB/DataStreams/NativeBlockOutputStream.h>
|
|
|
|
#include <DB/DataTypes/DataTypeTuple.h>
|
|
|
|
|
|
|
|
#include <ext/map.hpp>
|
|
|
|
#include <ext/enumerate.hpp>
|
|
|
|
#include <ext/range.hpp>
|
|
|
|
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
|
|
|
std::string DataTypeTuple::getName() const
|
|
|
|
{
|
|
|
|
std::stringstream s;
|
|
|
|
|
|
|
|
s << "Tuple(";
|
|
|
|
for (DataTypes::const_iterator it = elems.begin(); it != elems.end(); ++it)
|
|
|
|
s << (it == elems.begin() ? "" : ", ") << (*it)->getName();
|
|
|
|
s << ")";
|
|
|
|
|
|
|
|
return s.str();
|
|
|
|
}
|
|
|
|
|
2016-02-16 16:39:39 +00:00
|
|
|
|
|
|
|
static inline IColumn & extractElementColumn(IColumn & column, size_t idx)
|
|
|
|
{
|
2017-01-02 20:12:12 +00:00
|
|
|
return *static_cast<ColumnTuple &>(column).getData().getByPosition(idx).column.get();
|
2016-02-16 16:39:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline const IColumn & extractElementColumn(const IColumn & column, size_t idx)
|
|
|
|
{
|
2017-01-02 20:12:12 +00:00
|
|
|
return *static_cast<const ColumnTuple &>(column).getData().getByPosition(idx).column.get();
|
2016-02-16 16:39:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-02-14 02:37:42 +00:00
|
|
|
void DataTypeTuple::serializeBinary(const Field & field, WriteBuffer & ostr) const
|
|
|
|
{
|
|
|
|
const auto & tuple = get<const Tuple &>(field).t;
|
|
|
|
for (const auto & idx_elem : ext::enumerate(elems))
|
|
|
|
idx_elem.second->serializeBinary(tuple[idx_elem.first], ostr);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DataTypeTuple::deserializeBinary(Field & field, ReadBuffer & istr) const
|
|
|
|
{
|
|
|
|
const size_t size = elems.size();
|
|
|
|
field = Tuple(TupleBackend(size));
|
|
|
|
TupleBackend & tuple = get<Tuple &>(field).t;
|
|
|
|
for (const auto i : ext::range(0, size))
|
|
|
|
elems[i]->deserializeBinary(tuple[i], istr);
|
|
|
|
}
|
|
|
|
|
2016-02-16 16:39:39 +00:00
|
|
|
void DataTypeTuple::serializeBinary(const IColumn & column, size_t row_num, WriteBuffer & ostr) const
|
|
|
|
{
|
|
|
|
for (const auto & idx_elem : ext::enumerate(elems))
|
|
|
|
idx_elem.second->serializeBinary(extractElementColumn(column, idx_elem.first), row_num, ostr);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <typename F>
|
|
|
|
static void deserializeSafe(const DataTypes & elems, IColumn & column, ReadBuffer & istr, F && impl)
|
|
|
|
{
|
2017-03-25 20:12:56 +00:00
|
|
|
/// We use the assumption that tuples of zero size do not exist.
|
2016-02-16 16:39:39 +00:00
|
|
|
size_t old_size = extractElementColumn(column, 0).size();
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
impl();
|
|
|
|
}
|
|
|
|
catch (...)
|
|
|
|
{
|
|
|
|
for (const auto & i : ext::range(0, ext::size(elems)))
|
|
|
|
{
|
|
|
|
auto & element_column = extractElementColumn(column, i);
|
|
|
|
if (element_column.size() > old_size)
|
|
|
|
element_column.popBack(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
throw;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DataTypeTuple::deserializeBinary(IColumn & column, ReadBuffer & istr) const
|
|
|
|
{
|
|
|
|
deserializeSafe(elems, column, istr, [&]
|
|
|
|
{
|
|
|
|
for (const auto & i : ext::range(0, ext::size(elems)))
|
|
|
|
elems[i]->deserializeBinary(extractElementColumn(column, i), istr);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
void DataTypeTuple::serializeText(const IColumn & column, size_t row_num, WriteBuffer & ostr) const
|
2016-02-14 02:37:42 +00:00
|
|
|
{
|
|
|
|
writeChar('(', ostr);
|
|
|
|
for (const auto i : ext::range(0, ext::size(elems)))
|
|
|
|
{
|
|
|
|
if (i != 0)
|
|
|
|
writeChar(',', ostr);
|
2016-02-16 16:39:39 +00:00
|
|
|
elems[i]->serializeTextQuoted(extractElementColumn(column, i), row_num, ostr);
|
2016-02-14 02:37:42 +00:00
|
|
|
}
|
|
|
|
writeChar(')', ostr);
|
|
|
|
}
|
|
|
|
|
2016-02-16 16:39:39 +00:00
|
|
|
void DataTypeTuple::deserializeText(IColumn & column, ReadBuffer & istr) const
|
2016-02-14 02:37:42 +00:00
|
|
|
{
|
|
|
|
const size_t size = elems.size();
|
|
|
|
assertChar('(', istr);
|
2016-02-16 16:39:39 +00:00
|
|
|
|
|
|
|
deserializeSafe(elems, column, istr, [&]
|
2016-02-14 02:37:42 +00:00
|
|
|
{
|
2016-02-16 16:39:39 +00:00
|
|
|
for (const auto i : ext::range(0, size))
|
|
|
|
{
|
|
|
|
skipWhitespaceIfAny(istr);
|
|
|
|
if (i != 0)
|
|
|
|
assertChar(',', istr);
|
|
|
|
elems[i]->deserializeTextQuoted(extractElementColumn(column, i), istr);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2016-02-14 02:37:42 +00:00
|
|
|
skipWhitespaceIfAny(istr);
|
|
|
|
assertChar(')', istr);
|
|
|
|
}
|
|
|
|
|
2016-02-16 16:39:39 +00:00
|
|
|
void DataTypeTuple::serializeTextEscaped(const IColumn & column, size_t row_num, WriteBuffer & ostr) const
|
2016-02-14 02:37:42 +00:00
|
|
|
{
|
2016-02-16 16:39:39 +00:00
|
|
|
serializeText(column, row_num, ostr);
|
2016-02-14 02:37:42 +00:00
|
|
|
}
|
|
|
|
|
2016-02-16 16:39:39 +00:00
|
|
|
void DataTypeTuple::deserializeTextEscaped(IColumn & column, ReadBuffer & istr) const
|
2016-02-14 02:37:42 +00:00
|
|
|
{
|
2016-02-16 16:39:39 +00:00
|
|
|
deserializeText(column, istr);
|
2016-02-14 02:37:42 +00:00
|
|
|
}
|
|
|
|
|
2016-02-16 16:39:39 +00:00
|
|
|
void DataTypeTuple::serializeTextQuoted(const IColumn & column, size_t row_num, WriteBuffer & ostr) const
|
2016-02-14 02:37:42 +00:00
|
|
|
{
|
2016-02-16 16:39:39 +00:00
|
|
|
serializeText(column, row_num, ostr);
|
2016-02-14 02:37:42 +00:00
|
|
|
}
|
|
|
|
|
2016-02-16 16:39:39 +00:00
|
|
|
void DataTypeTuple::deserializeTextQuoted(IColumn & column, ReadBuffer & istr) const
|
2016-02-14 02:37:42 +00:00
|
|
|
{
|
2016-02-16 16:39:39 +00:00
|
|
|
deserializeText(column, istr);
|
2016-02-14 02:37:42 +00:00
|
|
|
}
|
|
|
|
|
2016-09-30 16:21:09 +00:00
|
|
|
void DataTypeTuple::serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr, bool force_quoting_64bit_integers) const
|
2016-02-14 02:37:42 +00:00
|
|
|
{
|
|
|
|
writeChar('[', ostr);
|
|
|
|
for (const auto i : ext::range(0, ext::size(elems)))
|
|
|
|
{
|
|
|
|
if (i != 0)
|
|
|
|
writeChar(',', ostr);
|
2016-09-30 16:21:09 +00:00
|
|
|
elems[i]->serializeTextJSON(extractElementColumn(column, i), row_num, ostr, force_quoting_64bit_integers);
|
2016-02-14 02:37:42 +00:00
|
|
|
}
|
|
|
|
writeChar(']', ostr);
|
|
|
|
}
|
|
|
|
|
2016-02-18 11:44:50 +00:00
|
|
|
void DataTypeTuple::deserializeTextJSON(IColumn & column, ReadBuffer & istr) const
|
|
|
|
{
|
|
|
|
const size_t size = elems.size();
|
|
|
|
assertChar('[', istr);
|
|
|
|
|
|
|
|
deserializeSafe(elems, column, istr, [&]
|
|
|
|
{
|
|
|
|
for (const auto i : ext::range(0, size))
|
|
|
|
{
|
|
|
|
skipWhitespaceIfAny(istr);
|
|
|
|
if (i != 0)
|
|
|
|
assertChar(',', istr);
|
|
|
|
elems[i]->deserializeTextJSON(extractElementColumn(column, i), istr);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
skipWhitespaceIfAny(istr);
|
|
|
|
assertChar(']', istr);
|
|
|
|
}
|
|
|
|
|
2016-02-16 16:39:39 +00:00
|
|
|
void DataTypeTuple::serializeTextXML(const IColumn & column, size_t row_num, WriteBuffer & ostr) const
|
2016-02-14 02:37:42 +00:00
|
|
|
{
|
|
|
|
writeCString("<tuple>", ostr);
|
|
|
|
for (const auto i : ext::range(0, ext::size(elems)))
|
|
|
|
{
|
|
|
|
writeCString("<elem>", ostr);
|
2016-02-16 16:39:39 +00:00
|
|
|
elems[i]->serializeTextXML(extractElementColumn(column, i), row_num, ostr);
|
2016-02-14 02:37:42 +00:00
|
|
|
writeCString("</elem>", ostr);
|
|
|
|
}
|
|
|
|
writeCString("</tuple>", ostr);
|
|
|
|
}
|
|
|
|
|
2016-02-16 16:39:39 +00:00
|
|
|
void DataTypeTuple::serializeTextCSV(const IColumn & column, size_t row_num, WriteBuffer & ostr) const
|
2016-02-14 02:37:42 +00:00
|
|
|
{
|
|
|
|
for (const auto i : ext::range(0, ext::size(elems)))
|
|
|
|
{
|
|
|
|
if (i != 0)
|
|
|
|
writeChar(',', ostr);
|
2016-02-16 16:39:39 +00:00
|
|
|
elems[i]->serializeTextCSV(extractElementColumn(column, i), row_num, ostr);
|
2016-02-14 02:37:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-16 16:39:39 +00:00
|
|
|
void DataTypeTuple::deserializeTextCSV(IColumn & column, ReadBuffer & istr, const char delimiter) const
|
2016-02-14 02:37:42 +00:00
|
|
|
{
|
2016-02-16 16:39:39 +00:00
|
|
|
deserializeSafe(elems, column, istr, [&]
|
2016-02-14 02:37:42 +00:00
|
|
|
{
|
2016-02-16 16:39:39 +00:00
|
|
|
const size_t size = elems.size();
|
|
|
|
for (const auto i : ext::range(0, size))
|
2016-02-14 02:37:42 +00:00
|
|
|
{
|
2016-02-16 16:39:39 +00:00
|
|
|
if (i != 0)
|
|
|
|
{
|
|
|
|
skipWhitespaceIfAny(istr);
|
|
|
|
assertChar(delimiter, istr);
|
|
|
|
skipWhitespaceIfAny(istr);
|
|
|
|
}
|
|
|
|
elems[i]->deserializeTextCSV(extractElementColumn(column, i), istr, delimiter);
|
2016-02-14 02:37:42 +00:00
|
|
|
}
|
2016-02-16 16:39:39 +00:00
|
|
|
});
|
2016-02-14 02:37:42 +00:00
|
|
|
}
|
|
|
|
|
2017-01-02 22:47:28 +00:00
|
|
|
void DataTypeTuple::serializeBinaryBulk(const IColumn & column, WriteBuffer & ostr, size_t offset, size_t limit) const
|
2016-02-14 02:37:42 +00:00
|
|
|
{
|
|
|
|
const ColumnTuple & real_column = static_cast<const ColumnTuple &>(column);
|
|
|
|
for (size_t i = 0, size = elems.size(); i < size; ++i)
|
2017-01-02 20:12:12 +00:00
|
|
|
NativeBlockOutputStream::writeData(*elems[i], real_column.getData().safeGetByPosition(i).column, ostr, offset, limit);
|
2016-02-14 02:37:42 +00:00
|
|
|
}
|
|
|
|
|
2017-01-02 22:47:28 +00:00
|
|
|
void DataTypeTuple::deserializeBinaryBulk(IColumn & column, ReadBuffer & istr, size_t limit, double avg_value_size_hint) const
|
2016-02-14 02:37:42 +00:00
|
|
|
{
|
|
|
|
ColumnTuple & real_column = static_cast<ColumnTuple &>(column);
|
|
|
|
for (size_t i = 0, size = elems.size(); i < size; ++i)
|
2017-01-02 20:12:12 +00:00
|
|
|
NativeBlockInputStream::readData(*elems[i], *real_column.getData().safeGetByPosition(i).column, istr, limit);
|
2016-02-14 02:37:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ColumnPtr DataTypeTuple::createColumn() const
|
|
|
|
{
|
|
|
|
Block tuple_block;
|
|
|
|
for (size_t i = 0, size = elems.size(); i < size; ++i)
|
|
|
|
{
|
|
|
|
ColumnWithTypeAndName col;
|
|
|
|
col.column = elems[i]->createColumn();
|
|
|
|
col.type = elems[i]->clone();
|
2016-08-04 23:35:07 +00:00
|
|
|
tuple_block.insert(std::move(col));
|
2016-02-14 02:37:42 +00:00
|
|
|
}
|
2016-05-28 05:31:36 +00:00
|
|
|
return std::make_shared<ColumnTuple>(tuple_block);
|
2016-02-14 02:37:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ColumnPtr DataTypeTuple::createConstColumn(size_t size, const Field & field) const
|
|
|
|
{
|
2016-05-28 07:48:40 +00:00
|
|
|
return std::make_shared<ColumnConstTuple>(size, get<const Tuple &>(field), std::make_shared<DataTypeTuple>(elems));
|
2016-02-14 02:37:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Field DataTypeTuple::getDefault() const
|
|
|
|
{
|
|
|
|
return Tuple(ext::map<TupleBackend>(elems, [] (const DataTypePtr & elem) { return elem->getDefault(); }));
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|