#pragma once #include #include #include namespace DB { /** Тип данных - кортеж. * Используется как промежуточный результат при вычислении выражений. * Также может быть использовать в качестве столбца - результата выполнения запроса. * Не может быть сохранён в таблицы. */ class DataTypeTuple : public IDataType { private: DataTypes elems; public: DataTypeTuple(DataTypes elems_) : elems(elems_) {} std::string 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(); } SharedPtr clone() const { return new DataTypeTuple(elems); } void serializeBinary(const Field & field, WriteBuffer & ostr) const { const Array & arr = get(field); for (size_t i = 0, size = elems.size(); i < size; ++i) elems[i]->serializeBinary(arr[i], ostr); } void deserializeBinary(Field & field, ReadBuffer & istr) const { size_t size = elems.size(); field = Array(size); Array & arr = get(field); for (size_t i = 0; i < size; ++i) elems[i]->deserializeBinary(arr[i], istr); } void serializeText(const Field & field, WriteBuffer & ostr) const { const Array & arr = get(field); writeChar('(', ostr); for (size_t i = 0, size = elems.size(); i < size; ++i) { if (i != 0) writeChar(',', ostr); elems[i]->serializeTextQuoted(arr[i], ostr); } writeChar(')', ostr); } void deserializeText(Field & field, ReadBuffer & istr) const { size_t size = elems.size(); field = Array(size); Array & arr = get(field); assertString("(", istr); for (size_t i = 0; i < size; ++i) { if (i != 0) assertString(",", istr); elems[i]->deserializeTextQuoted(arr[i], istr); } assertString(")", istr); } void serializeTextEscaped(const Field & field, WriteBuffer & ostr) const { serializeText(field, ostr); } void deserializeTextEscaped(Field & field, ReadBuffer & istr) const { deserializeText(field, istr); } void serializeTextQuoted(const Field & field, WriteBuffer & ostr) const { serializeText(field, ostr); } void deserializeTextQuoted(Field & field, ReadBuffer & istr) const { deserializeText(field, istr); } void serializeTextJSON(const Field & field, WriteBuffer & ostr) const { const Array & arr = get(field); writeChar('[', ostr); for (size_t i = 0, size = elems.size(); i < size; ++i) { if (i != 0) writeChar(',', ostr); elems[i]->serializeTextJSON(arr[i], ostr); } writeChar(']', ostr); } void serializeBinary(const IColumn & column, WriteBuffer & ostr, size_t offset = 0, size_t limit = 0) const { const ColumnTuple & real_column = static_cast(column); for (size_t i = 0, size = elems.size(); i < size; ++i) { const IColumn & nested_column = *real_column.getData().getByPosition(i).column; if (nested_column.isConst()) elems[i]->serializeBinary(*static_cast(nested_column).convertToFullColumn(), ostr, offset, limit); else elems[i]->serializeBinary(nested_column, ostr, offset, limit); } } /** limit обязательно должен быть в точности равен количеству сериализованных значений. * Именно из-за этого (невозможности читать меньший кусок записанных данных), Tuple не могут быть использованы для хранения данных в таблицах. * (Хотя могут быть использованы для передачи данных по сети в Native формате.) */ void deserializeBinary(IColumn & column, ReadBuffer & istr, size_t limit) const { ColumnTuple & real_column = static_cast(column); for (size_t i = 0, size = elems.size(); i < size; ++i) elems[i]->deserializeBinary(*real_column.getData().getByPosition(i).column, istr, limit); } ColumnPtr createColumn() const { Block tuple_block; for (size_t i = 0, size = elems.size(); i < size; ++i) { ColumnWithNameAndType col; col.column = elems[i]->createColumn(); tuple_block.insert(col); } return new ColumnTuple(tuple_block); } ColumnPtr createConstColumn(size_t size, const Field & field) const { return new ColumnConstArray(size, get(field), new DataTypeTuple(elems)); } Field getDefault() const { size_t size = elems.size(); Array res(size); for (size_t i = 0; i < size; ++i) res[i] = elems[i]->getDefault(); return res; } const DataTypes & getElements() const { return elems; } }; }