#include #include #include namespace DB { namespace { size_t getArrayDepth(DataTypePtr data_type, size_t max_depth) { size_t depth = 0; while (data_type && isArray(data_type) && depth != max_depth + 1) { depth++; data_type = static_cast(*data_type).getNestedType(); } return depth; } template class ContainerCreator : public boost::static_visitor { public: template Geometry operator()(const T & parser) const { return parser.createContainer(); } }; template class Getter : public boost::static_visitor { public: constexpr Getter(Geometry & container_, size_t i_) : container(container_) , i(i_) {} template void operator()(const T & parser) const { parser.get(container, i); } private: Geometry & container; size_t i; }; template Parser makeParser(const ColumnWithTypeAndName & col) { auto wanted_data_type = DataType::nestedDataType(); ColumnPtr casted = castColumn(col, DataType::nestedDataType()); if (!casted) { throw Exception("Failed to cast " + col.type->getName() + " to " + wanted_data_type->getName(), ErrorCodes::ILLEGAL_COLUMN); } return Parser(std::move(casted)); } } template Geometry createContainer(const GeometryFromColumnParser & parser) { static ContainerCreator> creator; return boost::apply_visitor(creator, parser); } template void get(const GeometryFromColumnParser & parser, Geometry & container, size_t i) { boost::apply_visitor(Getter(container, i), parser); } template GeometryFromColumnParser makeGeometryFromColumnParser(const ColumnWithTypeAndName & col) { switch (getArrayDepth(col.type, 3)) { case 0: return makeParser>(col); case 1: return makeParser>(col); case 2: return makeParser>(col); case 3: return makeParser>(col); default: throw Exception("Cannot parse geometry from column with type " + col.type->getName() + ", array depth is too big", ErrorCodes::ILLEGAL_COLUMN); } } /// Explicit instantiations to avoid linker errors. template Geometry createContainer(const GeometryFromColumnParser &); template Geometry createContainer(const GeometryFromColumnParser &); template void get(const GeometryFromColumnParser & parser, Geometry & container, size_t i); template void get(const GeometryFromColumnParser & parser, Geometry & container, size_t i); template GeometryFromColumnParser makeGeometryFromColumnParser(const ColumnWithTypeAndName & col); template GeometryFromColumnParser makeGeometryFromColumnParser(const ColumnWithTypeAndName & col); }