2018-01-15 19:07:47 +00:00
|
|
|
#include <Common/StringUtils/StringUtils.h>
|
2017-04-01 09:19:00 +00:00
|
|
|
#include <Columns/ColumnTuple.h>
|
2018-06-10 19:22:49 +00:00
|
|
|
#include <Formats/FormatSettings.h>
|
2017-04-01 09:19:00 +00:00
|
|
|
#include <DataTypes/DataTypeTuple.h>
|
2017-12-25 18:58:39 +00:00
|
|
|
#include <DataTypes/DataTypeArray.h>
|
2017-07-16 03:05:40 +00:00
|
|
|
#include <DataTypes/DataTypeFactory.h>
|
|
|
|
#include <Parsers/IAST.h>
|
2017-12-23 04:29:34 +00:00
|
|
|
#include <Parsers/ASTNameTypePair.h>
|
|
|
|
#include <Common/typeid_cast.h>
|
2017-12-03 02:59:59 +00:00
|
|
|
#include <IO/WriteHelpers.h>
|
|
|
|
#include <IO/ReadHelpers.h>
|
2017-12-23 04:29:34 +00:00
|
|
|
#include <IO/WriteBufferFromString.h>
|
|
|
|
#include <IO/Operators.h>
|
2016-02-14 02:37:42 +00:00
|
|
|
|
2017-06-06 17:18:32 +00:00
|
|
|
#include <ext/map.h>
|
|
|
|
#include <ext/enumerate.h>
|
|
|
|
#include <ext/range.h>
|
2016-02-14 02:37:42 +00:00
|
|
|
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
2017-07-16 03:05:40 +00:00
|
|
|
namespace ErrorCodes
|
|
|
|
{
|
|
|
|
extern const int EMPTY_DATA_PASSED;
|
2017-12-23 04:29:34 +00:00
|
|
|
extern const int NUMBER_OF_ARGUMENTS_DOESNT_MATCH;
|
|
|
|
extern const int DUPLICATE_COLUMN;
|
|
|
|
extern const int BAD_ARGUMENTS;
|
2017-12-24 09:34:40 +00:00
|
|
|
extern const int NOT_FOUND_COLUMN_IN_BLOCK;
|
2017-07-16 03:05:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-23 04:29:34 +00:00
|
|
|
DataTypeTuple::DataTypeTuple(const DataTypes & elems_)
|
|
|
|
: elems(elems_), have_explicit_names(false)
|
|
|
|
{
|
|
|
|
/// Automatically assigned names in form of '1', '2', ...
|
|
|
|
size_t size = elems.size();
|
|
|
|
names.resize(size);
|
|
|
|
for (size_t i = 0; i < size; ++i)
|
|
|
|
names[i] = toString(i + 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DataTypeTuple::DataTypeTuple(const DataTypes & elems_, const Strings & names_)
|
|
|
|
: elems(elems_), names(names_), have_explicit_names(true)
|
|
|
|
{
|
|
|
|
size_t size = elems.size();
|
|
|
|
if (names.size() != size)
|
|
|
|
throw Exception("Wrong number of names passed to constructor of DataTypeTuple", ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
|
|
|
|
|
|
|
|
std::unordered_set<String> names_set;
|
|
|
|
for (size_t i = 0; i < size; ++i)
|
|
|
|
{
|
|
|
|
if (names[i].empty())
|
|
|
|
throw Exception("Names of tuple elements cannot be empty", ErrorCodes::BAD_ARGUMENTS);
|
|
|
|
|
|
|
|
if (isNumericASCII(names[i][0]))
|
|
|
|
throw Exception("Explicitly specified names of tuple elements cannot start with digit", ErrorCodes::BAD_ARGUMENTS);
|
|
|
|
|
|
|
|
if (!names_set.insert(names[i]).second)
|
|
|
|
throw Exception("Names of tuple elements must be unique", ErrorCodes::DUPLICATE_COLUMN);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2018-12-13 13:41:47 +00:00
|
|
|
std::string DataTypeTuple::doGetName() const
|
2016-02-14 02:37:42 +00:00
|
|
|
{
|
2017-12-23 04:29:34 +00:00
|
|
|
size_t size = elems.size();
|
|
|
|
WriteBufferFromOwnString s;
|
2016-02-14 02:37:42 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
s << "Tuple(";
|
2017-12-23 04:29:34 +00:00
|
|
|
for (size_t i = 0; i < size; ++i)
|
|
|
|
{
|
|
|
|
if (i != 0)
|
|
|
|
s << ", ";
|
|
|
|
|
|
|
|
if (have_explicit_names)
|
|
|
|
s << backQuoteIfNeed(names[i]) << ' ';
|
|
|
|
|
|
|
|
s << elems[i]->getName();
|
|
|
|
}
|
2017-04-01 07:20:54 +00:00
|
|
|
s << ")";
|
2016-02-14 02:37:42 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
return s.str();
|
2016-02-14 02:37:42 +00:00
|
|
|
}
|
|
|
|
|
2016-02-16 16:39:39 +00:00
|
|
|
|
|
|
|
static inline IColumn & extractElementColumn(IColumn & column, size_t idx)
|
|
|
|
{
|
2017-12-16 01:21:59 +00:00
|
|
|
return static_cast<ColumnTuple &>(column).getColumn(idx);
|
2016-02-16 16:39:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline const IColumn & extractElementColumn(const IColumn & column, size_t idx)
|
|
|
|
{
|
2017-12-16 01:21:59 +00:00
|
|
|
return static_cast<const ColumnTuple &>(column).getColumn(idx);
|
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
|
|
|
|
{
|
2018-05-16 00:34:56 +00:00
|
|
|
const auto & tuple = get<const Tuple &>(field).toUnderType();
|
2019-01-04 12:10:00 +00:00
|
|
|
for (const auto idx_elem : ext::enumerate(elems))
|
2017-04-01 07:20:54 +00:00
|
|
|
idx_elem.second->serializeBinary(tuple[idx_elem.first], ostr);
|
2016-02-14 02:37:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void DataTypeTuple::deserializeBinary(Field & field, ReadBuffer & istr) const
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
const size_t size = elems.size();
|
|
|
|
field = Tuple(TupleBackend(size));
|
2018-05-16 00:34:56 +00:00
|
|
|
TupleBackend & tuple = get<Tuple &>(field).toUnderType();
|
2017-04-01 07:20:54 +00:00
|
|
|
for (const auto i : ext::range(0, size))
|
|
|
|
elems[i]->deserializeBinary(tuple[i], istr);
|
2016-02-14 02:37:42 +00:00
|
|
|
}
|
|
|
|
|
2016-02-16 16:39:39 +00:00
|
|
|
void DataTypeTuple::serializeBinary(const IColumn & column, size_t row_num, WriteBuffer & ostr) const
|
|
|
|
{
|
2019-01-04 12:10:00 +00:00
|
|
|
for (const auto idx_elem : ext::enumerate(elems))
|
2017-04-01 07:20:54 +00:00
|
|
|
idx_elem.second->serializeBinary(extractElementColumn(column, idx_elem.first), row_num, ostr);
|
2016-02-16 16:39:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <typename F>
|
2017-09-01 21:37:57 +00:00
|
|
|
static void addElementSafe(const DataTypes & elems, IColumn & column, F && impl)
|
2016-02-16 16:39:39 +00:00
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
/// We use the assumption that tuples of zero size do not exist.
|
2017-12-08 00:50:25 +00:00
|
|
|
size_t old_size = column.size();
|
2017-04-01 07:20:54 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
2016-02-16 16:39:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DataTypeTuple::deserializeBinary(IColumn & column, ReadBuffer & istr) const
|
|
|
|
{
|
2017-09-01 21:37:57 +00:00
|
|
|
addElementSafe(elems, column, [&]
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
|
|
|
for (const auto & i : ext::range(0, ext::size(elems)))
|
|
|
|
elems[i]->deserializeBinary(extractElementColumn(column, i), istr);
|
|
|
|
});
|
2016-02-16 16:39:39 +00:00
|
|
|
}
|
|
|
|
|
2018-06-08 01:51:55 +00:00
|
|
|
void DataTypeTuple::serializeText(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings & settings) const
|
2016-02-14 02:37:42 +00:00
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
writeChar('(', ostr);
|
|
|
|
for (const auto i : ext::range(0, ext::size(elems)))
|
|
|
|
{
|
|
|
|
if (i != 0)
|
|
|
|
writeChar(',', ostr);
|
2018-12-13 13:41:47 +00:00
|
|
|
elems[i]->serializeAsTextQuoted(extractElementColumn(column, i), row_num, ostr, settings);
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
|
|
|
writeChar(')', ostr);
|
2016-02-14 02:37:42 +00:00
|
|
|
}
|
|
|
|
|
2018-06-08 01:51:55 +00:00
|
|
|
void DataTypeTuple::deserializeText(IColumn & column, ReadBuffer & istr, const FormatSettings & settings) const
|
2016-02-14 02:37:42 +00:00
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
const size_t size = elems.size();
|
|
|
|
assertChar('(', istr);
|
|
|
|
|
2017-09-01 21:37:57 +00:00
|
|
|
addElementSafe(elems, column, [&]
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
|
|
|
for (const auto i : ext::range(0, size))
|
|
|
|
{
|
|
|
|
skipWhitespaceIfAny(istr);
|
|
|
|
if (i != 0)
|
2017-12-03 08:16:49 +00:00
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
assertChar(',', istr);
|
2017-12-03 08:16:49 +00:00
|
|
|
skipWhitespaceIfAny(istr);
|
|
|
|
}
|
2018-12-13 13:41:47 +00:00
|
|
|
elems[i]->deserializeAsTextQuoted(extractElementColumn(column, i), istr, settings);
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
skipWhitespaceIfAny(istr);
|
|
|
|
assertChar(')', istr);
|
2016-02-14 02:37:42 +00:00
|
|
|
}
|
|
|
|
|
2018-06-05 21:39:01 +00:00
|
|
|
void DataTypeTuple::serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings & settings) const
|
2016-02-14 02:37:42 +00:00
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
writeChar('[', ostr);
|
|
|
|
for (const auto i : ext::range(0, ext::size(elems)))
|
|
|
|
{
|
|
|
|
if (i != 0)
|
|
|
|
writeChar(',', ostr);
|
2018-12-13 13:41:47 +00:00
|
|
|
elems[i]->serializeAsTextJSON(extractElementColumn(column, i), row_num, ostr, settings);
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
|
|
|
writeChar(']', ostr);
|
2016-02-14 02:37:42 +00:00
|
|
|
}
|
|
|
|
|
2018-06-08 01:51:55 +00:00
|
|
|
void DataTypeTuple::deserializeTextJSON(IColumn & column, ReadBuffer & istr, const FormatSettings & settings) const
|
2016-02-18 11:44:50 +00:00
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
const size_t size = elems.size();
|
|
|
|
assertChar('[', istr);
|
|
|
|
|
2017-09-01 21:37:57 +00:00
|
|
|
addElementSafe(elems, column, [&]
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
|
|
|
for (const auto i : ext::range(0, size))
|
|
|
|
{
|
|
|
|
skipWhitespaceIfAny(istr);
|
|
|
|
if (i != 0)
|
2017-12-03 08:16:49 +00:00
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
assertChar(',', istr);
|
2017-12-03 08:16:49 +00:00
|
|
|
skipWhitespaceIfAny(istr);
|
|
|
|
}
|
2018-12-13 13:41:47 +00:00
|
|
|
elems[i]->deserializeAsTextJSON(extractElementColumn(column, i), istr, settings);
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
skipWhitespaceIfAny(istr);
|
|
|
|
assertChar(']', istr);
|
2016-02-18 11:44:50 +00:00
|
|
|
}
|
|
|
|
|
2018-06-08 01:51:55 +00:00
|
|
|
void DataTypeTuple::serializeTextXML(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings & settings) const
|
2016-02-14 02:37:42 +00:00
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
writeCString("<tuple>", ostr);
|
|
|
|
for (const auto i : ext::range(0, ext::size(elems)))
|
|
|
|
{
|
|
|
|
writeCString("<elem>", ostr);
|
2018-12-13 13:41:47 +00:00
|
|
|
elems[i]->serializeAsTextXML(extractElementColumn(column, i), row_num, ostr, settings);
|
2017-04-01 07:20:54 +00:00
|
|
|
writeCString("</elem>", ostr);
|
|
|
|
}
|
|
|
|
writeCString("</tuple>", ostr);
|
2016-02-14 02:37:42 +00:00
|
|
|
}
|
|
|
|
|
2018-06-08 01:51:55 +00:00
|
|
|
void DataTypeTuple::serializeTextCSV(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings & settings) const
|
2016-02-14 02:37:42 +00:00
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
for (const auto i : ext::range(0, ext::size(elems)))
|
|
|
|
{
|
|
|
|
if (i != 0)
|
|
|
|
writeChar(',', ostr);
|
2018-12-13 13:41:47 +00:00
|
|
|
elems[i]->serializeAsTextCSV(extractElementColumn(column, i), row_num, ostr, settings);
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
2016-02-14 02:37:42 +00:00
|
|
|
}
|
|
|
|
|
2018-06-05 21:39:01 +00:00
|
|
|
void DataTypeTuple::deserializeTextCSV(IColumn & column, ReadBuffer & istr, const FormatSettings & settings) const
|
2016-02-14 02:37:42 +00:00
|
|
|
{
|
2017-09-01 21:37:57 +00:00
|
|
|
addElementSafe(elems, column, [&]
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
|
|
|
const size_t size = elems.size();
|
|
|
|
for (const auto i : ext::range(0, size))
|
|
|
|
{
|
|
|
|
if (i != 0)
|
|
|
|
{
|
|
|
|
skipWhitespaceIfAny(istr);
|
2018-06-08 01:51:55 +00:00
|
|
|
assertChar(settings.csv.delimiter, istr);
|
2017-04-01 07:20:54 +00:00
|
|
|
skipWhitespaceIfAny(istr);
|
|
|
|
}
|
2018-12-13 13:41:47 +00:00
|
|
|
elems[i]->deserializeAsTextCSV(extractElementColumn(column, i), istr, settings);
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
|
|
|
});
|
2016-02-14 02:37:42 +00:00
|
|
|
}
|
|
|
|
|
2018-06-07 18:14:37 +00:00
|
|
|
void DataTypeTuple::enumerateStreams(const StreamCallback & callback, SubstreamPath & path) const
|
2016-02-14 02:37:42 +00:00
|
|
|
{
|
2017-12-03 02:59:59 +00:00
|
|
|
path.push_back(Substream::TupleElement);
|
|
|
|
for (const auto i : ext::range(0, ext::size(elems)))
|
|
|
|
{
|
2017-12-23 04:29:34 +00:00
|
|
|
path.back().tuple_element_name = names[i];
|
2017-12-03 02:59:59 +00:00
|
|
|
elems[i]->enumerateStreams(callback, path);
|
|
|
|
}
|
2018-06-07 18:14:37 +00:00
|
|
|
path.pop_back();
|
|
|
|
}
|
|
|
|
|
|
|
|
struct SerializeBinaryBulkStateTuple : public IDataType::SerializeBinaryBulkState
|
|
|
|
{
|
|
|
|
std::vector<IDataType::SerializeBinaryBulkStatePtr> states;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct DeserializeBinaryBulkStateTuple : public IDataType::DeserializeBinaryBulkState
|
|
|
|
{
|
|
|
|
std::vector<IDataType::DeserializeBinaryBulkStatePtr> states;
|
|
|
|
};
|
|
|
|
|
|
|
|
static SerializeBinaryBulkStateTuple * checkAndGetTupleSerializeState(IDataType::SerializeBinaryBulkStatePtr & state)
|
|
|
|
{
|
|
|
|
if (!state)
|
|
|
|
throw Exception("Got empty state for DataTypeTuple.", ErrorCodes::LOGICAL_ERROR);
|
|
|
|
|
|
|
|
auto * tuple_state = typeid_cast<SerializeBinaryBulkStateTuple *>(state.get());
|
|
|
|
if (!tuple_state)
|
2018-08-09 09:28:52 +00:00
|
|
|
{
|
|
|
|
auto & state_ref = *state;
|
2018-06-07 18:14:37 +00:00
|
|
|
throw Exception("Invalid SerializeBinaryBulkState for DataTypeTuple. Expected: "
|
|
|
|
+ demangle(typeid(SerializeBinaryBulkStateTuple).name()) + ", got "
|
2018-08-09 09:28:52 +00:00
|
|
|
+ demangle(typeid(state_ref).name()), ErrorCodes::LOGICAL_ERROR);
|
|
|
|
}
|
2018-06-07 18:14:37 +00:00
|
|
|
|
|
|
|
return tuple_state;
|
|
|
|
}
|
|
|
|
|
|
|
|
static DeserializeBinaryBulkStateTuple * checkAndGetTupleDeserializeState(IDataType::DeserializeBinaryBulkStatePtr & state)
|
|
|
|
{
|
|
|
|
if (!state)
|
|
|
|
throw Exception("Got empty state for DataTypeTuple.", ErrorCodes::LOGICAL_ERROR);
|
|
|
|
|
|
|
|
auto * tuple_state = typeid_cast<DeserializeBinaryBulkStateTuple *>(state.get());
|
|
|
|
if (!tuple_state)
|
2018-08-09 09:28:52 +00:00
|
|
|
{
|
|
|
|
auto & state_ref = *state;
|
2018-06-07 18:14:37 +00:00
|
|
|
throw Exception("Invalid DeserializeBinaryBulkState for DataTypeTuple. Expected: "
|
|
|
|
+ demangle(typeid(DeserializeBinaryBulkStateTuple).name()) + ", got "
|
2018-08-09 09:28:52 +00:00
|
|
|
+ demangle(typeid(state_ref).name()), ErrorCodes::LOGICAL_ERROR);
|
|
|
|
}
|
2018-06-07 18:14:37 +00:00
|
|
|
|
|
|
|
return tuple_state;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DataTypeTuple::serializeBinaryBulkStatePrefix(
|
|
|
|
SerializeBinaryBulkSettings & settings,
|
|
|
|
SerializeBinaryBulkStatePtr & state) const
|
|
|
|
{
|
|
|
|
auto tuple_state = std::make_shared<SerializeBinaryBulkStateTuple>();
|
|
|
|
tuple_state->states.resize(elems.size());
|
|
|
|
|
|
|
|
settings.path.push_back(Substream::TupleElement);
|
|
|
|
for (size_t i = 0; i < elems.size(); ++i)
|
|
|
|
{
|
|
|
|
settings.path.back().tuple_element_name = names[i];
|
|
|
|
elems[i]->serializeBinaryBulkStatePrefix(settings, tuple_state->states[i]);
|
|
|
|
}
|
|
|
|
settings.path.pop_back();
|
|
|
|
|
|
|
|
state = std::move(tuple_state);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DataTypeTuple::serializeBinaryBulkStateSuffix(
|
|
|
|
SerializeBinaryBulkSettings & settings,
|
|
|
|
SerializeBinaryBulkStatePtr & state) const
|
|
|
|
{
|
|
|
|
auto * tuple_state = checkAndGetTupleSerializeState(state);
|
|
|
|
|
|
|
|
settings.path.push_back(Substream::TupleElement);
|
|
|
|
for (size_t i = 0; i < elems.size(); ++i)
|
|
|
|
{
|
|
|
|
settings.path.back().tuple_element_name = names[i];
|
|
|
|
elems[i]->serializeBinaryBulkStateSuffix(settings, tuple_state->states[i]);
|
|
|
|
}
|
|
|
|
settings.path.pop_back();
|
|
|
|
}
|
|
|
|
|
|
|
|
void DataTypeTuple::deserializeBinaryBulkStatePrefix(
|
|
|
|
DeserializeBinaryBulkSettings & settings,
|
|
|
|
DeserializeBinaryBulkStatePtr & state) const
|
|
|
|
{
|
|
|
|
auto tuple_state = std::make_shared<DeserializeBinaryBulkStateTuple>();
|
|
|
|
tuple_state->states.resize(elems.size());
|
|
|
|
|
|
|
|
settings.path.push_back(Substream::TupleElement);
|
|
|
|
for (size_t i = 0; i < elems.size(); ++i)
|
|
|
|
{
|
|
|
|
settings.path.back().tuple_element_name = names[i];
|
|
|
|
elems[i]->deserializeBinaryBulkStatePrefix(settings, tuple_state->states[i]);
|
|
|
|
}
|
|
|
|
settings.path.pop_back();
|
|
|
|
|
|
|
|
state = std::move(tuple_state);
|
2016-02-14 02:37:42 +00:00
|
|
|
}
|
|
|
|
|
2017-12-03 02:59:59 +00:00
|
|
|
void DataTypeTuple::serializeBinaryBulkWithMultipleStreams(
|
|
|
|
const IColumn & column,
|
|
|
|
size_t offset,
|
2019-02-19 00:41:24 +00:00
|
|
|
size_t limit,
|
2018-06-07 18:14:37 +00:00
|
|
|
SerializeBinaryBulkSettings & settings,
|
|
|
|
SerializeBinaryBulkStatePtr & state) const
|
2016-02-14 02:37:42 +00:00
|
|
|
{
|
2018-06-07 18:14:37 +00:00
|
|
|
auto * tuple_state = checkAndGetTupleSerializeState(state);
|
|
|
|
|
|
|
|
settings.path.push_back(Substream::TupleElement);
|
2017-12-03 02:59:59 +00:00
|
|
|
for (const auto i : ext::range(0, ext::size(elems)))
|
|
|
|
{
|
2018-06-07 18:14:37 +00:00
|
|
|
settings.path.back().tuple_element_name = names[i];
|
|
|
|
auto & element_col = extractElementColumn(column, i);
|
|
|
|
elems[i]->serializeBinaryBulkWithMultipleStreams(element_col, offset, limit, settings, tuple_state->states[i]);
|
2017-12-03 02:59:59 +00:00
|
|
|
}
|
2018-06-07 18:14:37 +00:00
|
|
|
settings.path.pop_back();
|
2017-12-03 02:59:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void DataTypeTuple::deserializeBinaryBulkWithMultipleStreams(
|
|
|
|
IColumn & column,
|
2019-02-19 00:41:24 +00:00
|
|
|
size_t limit,
|
2018-06-07 18:14:37 +00:00
|
|
|
DeserializeBinaryBulkSettings & settings,
|
|
|
|
DeserializeBinaryBulkStatePtr & state) const
|
2017-12-03 02:59:59 +00:00
|
|
|
{
|
2018-06-07 18:14:37 +00:00
|
|
|
auto * tuple_state = checkAndGetTupleDeserializeState(state);
|
2018-05-21 16:21:15 +00:00
|
|
|
|
2018-06-07 18:14:37 +00:00
|
|
|
settings.path.push_back(Substream::TupleElement);
|
2018-11-21 03:09:56 +00:00
|
|
|
settings.avg_value_size_hint = 0;
|
2017-12-03 02:59:59 +00:00
|
|
|
for (const auto i : ext::range(0, ext::size(elems)))
|
|
|
|
{
|
2018-06-07 18:14:37 +00:00
|
|
|
settings.path.back().tuple_element_name = names[i];
|
|
|
|
auto & element_col = extractElementColumn(column, i);
|
|
|
|
elems[i]->deserializeBinaryBulkWithMultipleStreams(element_col, limit, settings, tuple_state->states[i]);
|
2017-12-03 02:59:59 +00:00
|
|
|
}
|
2018-06-07 18:14:37 +00:00
|
|
|
settings.path.pop_back();
|
2016-02-14 02:37:42 +00:00
|
|
|
}
|
|
|
|
|
2019-02-26 14:06:05 +00:00
|
|
|
void DataTypeTuple::serializeProtobuf(const IColumn & column, size_t row_num, ProtobufWriter & protobuf, size_t & value_index) const
|
2019-01-23 19:41:18 +00:00
|
|
|
{
|
2019-02-26 14:06:05 +00:00
|
|
|
for (; value_index < elems.size(); ++value_index)
|
|
|
|
{
|
|
|
|
size_t stored = 0;
|
|
|
|
elems[value_index]->serializeProtobuf(extractElementColumn(column, value_index), row_num, protobuf, stored);
|
|
|
|
if (!stored)
|
|
|
|
break;
|
|
|
|
}
|
2019-01-23 19:41:18 +00:00
|
|
|
}
|
|
|
|
|
2019-02-19 20:01:31 +00:00
|
|
|
void DataTypeTuple::deserializeProtobuf(IColumn & column, ProtobufReader & protobuf, bool allow_add_row, bool & row_added) const
|
|
|
|
{
|
|
|
|
row_added = false;
|
|
|
|
bool all_elements_get_row = true;
|
|
|
|
addElementSafe(elems, column, [&]
|
|
|
|
{
|
|
|
|
for (const auto & i : ext::range(0, ext::size(elems)))
|
|
|
|
{
|
|
|
|
bool element_row_added;
|
|
|
|
elems[i]->deserializeProtobuf(extractElementColumn(column, i), protobuf, allow_add_row, element_row_added);
|
|
|
|
all_elements_get_row &= element_row_added;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
row_added = all_elements_get_row;
|
|
|
|
}
|
|
|
|
|
2017-12-14 03:56:56 +00:00
|
|
|
MutableColumnPtr DataTypeTuple::createColumn() const
|
2016-02-14 02:37:42 +00:00
|
|
|
{
|
2017-12-08 00:50:25 +00:00
|
|
|
size_t size = elems.size();
|
2018-03-20 14:17:09 +00:00
|
|
|
MutableColumns tuple_columns(size);
|
2017-12-08 00:50:25 +00:00
|
|
|
for (size_t i = 0; i < size; ++i)
|
|
|
|
tuple_columns[i] = elems[i]->createColumn();
|
2018-03-20 14:17:09 +00:00
|
|
|
return ColumnTuple::create(std::move(tuple_columns));
|
2016-02-14 02:37:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Field DataTypeTuple::getDefault() const
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
return Tuple(ext::map<TupleBackend>(elems, [] (const DataTypePtr & elem) { return elem->getDefault(); }));
|
2016-02-14 02:37:42 +00:00
|
|
|
}
|
|
|
|
|
2017-09-01 21:37:57 +00:00
|
|
|
void DataTypeTuple::insertDefaultInto(IColumn & column) const
|
|
|
|
{
|
|
|
|
addElementSafe(elems, column, [&]
|
|
|
|
{
|
|
|
|
for (const auto & i : ext::range(0, ext::size(elems)))
|
|
|
|
elems[i]->insertDefaultInto(extractElementColumn(column, i));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2017-12-23 01:05:29 +00:00
|
|
|
bool DataTypeTuple::equals(const IDataType & rhs) const
|
|
|
|
{
|
|
|
|
if (typeid(rhs) != typeid(*this))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
const DataTypeTuple & rhs_tuple = static_cast<const DataTypeTuple &>(rhs);
|
|
|
|
|
|
|
|
size_t size = elems.size();
|
|
|
|
if (size != rhs_tuple.elems.size())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
for (size_t i = 0; i < size; ++i)
|
|
|
|
if (!elems[i]->equals(*rhs_tuple.elems[i]))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-07-16 03:05:40 +00:00
|
|
|
|
2017-12-24 09:34:40 +00:00
|
|
|
size_t DataTypeTuple::getPositionByName(const String & name) const
|
|
|
|
{
|
|
|
|
size_t size = elems.size();
|
|
|
|
for (size_t i = 0; i < size; ++i)
|
|
|
|
if (names[i] == name)
|
|
|
|
return i;
|
|
|
|
throw Exception("Tuple doesn't have element with name '" + name + "'", ErrorCodes::NOT_FOUND_COLUMN_IN_BLOCK);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-09 06:32:22 +00:00
|
|
|
bool DataTypeTuple::textCanContainOnlyValidUTF8() const
|
|
|
|
{
|
|
|
|
return std::all_of(elems.begin(), elems.end(), [](auto && elem) { return elem->textCanContainOnlyValidUTF8(); });
|
|
|
|
}
|
|
|
|
|
|
|
|
bool DataTypeTuple::haveMaximumSizeOfValue() const
|
|
|
|
{
|
|
|
|
return std::all_of(elems.begin(), elems.end(), [](auto && elem) { return elem->haveMaximumSizeOfValue(); });
|
|
|
|
}
|
|
|
|
|
2017-12-20 07:36:30 +00:00
|
|
|
bool DataTypeTuple::isComparable() const
|
|
|
|
{
|
|
|
|
return std::all_of(elems.begin(), elems.end(), [](auto && elem) { return elem->isComparable(); });
|
|
|
|
}
|
|
|
|
|
2017-12-09 06:32:22 +00:00
|
|
|
size_t DataTypeTuple::getMaximumSizeOfValueInMemory() const
|
|
|
|
{
|
|
|
|
size_t res = 0;
|
|
|
|
for (const auto & elem : elems)
|
|
|
|
res += elem->getMaximumSizeOfValueInMemory();
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t DataTypeTuple::getSizeOfValueInMemory() const
|
|
|
|
{
|
|
|
|
size_t res = 0;
|
|
|
|
for (const auto & elem : elems)
|
|
|
|
res += elem->getSizeOfValueInMemory();
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-07-16 03:05:40 +00:00
|
|
|
static DataTypePtr create(const ASTPtr & arguments)
|
|
|
|
{
|
2017-12-22 03:55:49 +00:00
|
|
|
if (!arguments || arguments->children.empty())
|
2017-07-16 03:05:40 +00:00
|
|
|
throw Exception("Tuple cannot be empty", ErrorCodes::EMPTY_DATA_PASSED);
|
|
|
|
|
|
|
|
DataTypes nested_types;
|
|
|
|
nested_types.reserve(arguments->children.size());
|
|
|
|
|
2017-12-23 04:29:34 +00:00
|
|
|
Strings names;
|
|
|
|
names.reserve(arguments->children.size());
|
|
|
|
|
2017-07-16 03:05:40 +00:00
|
|
|
for (const ASTPtr & child : arguments->children)
|
2017-12-23 04:29:34 +00:00
|
|
|
{
|
|
|
|
if (const ASTNameTypePair * name_and_type_pair = typeid_cast<const ASTNameTypePair *>(child.get()))
|
|
|
|
{
|
|
|
|
nested_types.emplace_back(DataTypeFactory::instance().get(name_and_type_pair->type));
|
|
|
|
names.emplace_back(name_and_type_pair->name);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
nested_types.emplace_back(DataTypeFactory::instance().get(child));
|
|
|
|
}
|
2017-07-16 03:05:40 +00:00
|
|
|
|
2017-12-23 04:29:34 +00:00
|
|
|
if (names.empty())
|
|
|
|
return std::make_shared<DataTypeTuple>(nested_types);
|
|
|
|
else if (names.size() != nested_types.size())
|
|
|
|
throw Exception("Names are specified not for all elements of Tuple type", ErrorCodes::BAD_ARGUMENTS);
|
|
|
|
else
|
|
|
|
return std::make_shared<DataTypeTuple>(nested_types, names);
|
2017-07-16 03:05:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void registerDataTypeTuple(DataTypeFactory & factory)
|
|
|
|
{
|
|
|
|
factory.registerDataType("Tuple", create);
|
|
|
|
}
|
|
|
|
|
2017-12-25 18:58:39 +00:00
|
|
|
void registerDataTypeNested(DataTypeFactory & factory)
|
|
|
|
{
|
|
|
|
/// Nested(...) data type is just a sugar for Array(Tuple(...))
|
|
|
|
factory.registerDataType("Nested", [&factory](const ASTPtr & arguments)
|
|
|
|
{
|
|
|
|
return std::make_shared<DataTypeArray>(factory.get("Tuple", arguments));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2016-02-14 02:37:42 +00:00
|
|
|
}
|