#include #include namespace DB { namespace ErrorCodes { extern const int BAD_ARGUMENTS; extern const int LOGICAL_ERROR; extern const int ILLEGAL_TYPE_OF_ARGUMENT; } template std::vector PointFromColumnConverter::convertImpl(size_t shift, size_t count) const { const auto * tuple = typeid_cast(col.get()); const auto & tuple_columns = tuple->getColumns(); const auto * x_data = typeid_cast(tuple_columns[0].get()); const auto * y_data = typeid_cast(tuple_columns[1].get()); const auto * first_container = x_data->getData().data() + shift; const auto * second_container = y_data->getData().data() + shift; std::vector answer(count); for (size_t i = 0; i < count; ++i) { const Float64 first = first_container[i]; const Float64 second = second_container[i]; if (isNaN(first) || isNaN(second)) throw Exception("Point's component must not be NaN", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); if (isinf(first) || isinf(second)) throw Exception("Point's component must not be infinite", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); answer[i] = Point(first, second); } return answer; } template std::vector> RingFromColumnConverter::convert() const { const IColumn::Offsets & offsets = typeid_cast(*col).getOffsets(); size_t prev_offset = 0; std::vector> answer; answer.reserve(offsets.size()); for (size_t offset : offsets) { auto tmp = point_converter.convertImpl(prev_offset, offset - prev_offset); answer.emplace_back(tmp.begin(), tmp.end()); prev_offset = offset; } return answer; } template std::vector> PolygonFromColumnConverter::convert() const { const IColumn::Offsets & offsets = typeid_cast(*col).getOffsets(); std::vector> answer(offsets.size()); auto all_rings = ring_converter.convert(); auto prev_offset = 0; for (size_t iter = 0; iter < offsets.size(); ++iter) { const auto current_array_size = offsets[iter] - prev_offset; answer[iter].outer() = std::move(all_rings[prev_offset]); answer[iter].inners().reserve(current_array_size); for (size_t inner_holes = prev_offset + 1; inner_holes < offsets[iter]; ++inner_holes) answer[iter].inners().emplace_back(std::move(all_rings[inner_holes])); prev_offset = offsets[iter]; } return answer; } template std::vector> MultiPolygonFromColumnConverter::convert() const { const IColumn::Offsets & offsets = typeid_cast(*col).getOffsets(); size_t prev_offset = 0; std::vector> answer(offsets.size()); auto all_polygons = polygon_converter.convert(); for (size_t iter = 0; iter < offsets.size(); ++iter) { for (size_t polygon_iter = prev_offset; polygon_iter < offsets[iter]; ++polygon_iter) answer[iter].emplace_back(std::move(all_polygons[polygon_iter])); prev_offset = offsets[iter]; } return answer; } template class PointFromColumnConverter; template class PointFromColumnConverter; template class RingFromColumnConverter; template class RingFromColumnConverter; template class PolygonFromColumnConverter; template class PolygonFromColumnConverter; template class MultiPolygonFromColumnConverter; template class MultiPolygonFromColumnConverter; template typename Desired> void checkColumnTypeOrThrow(const ColumnWithTypeAndName & column) { DataTypePtr desired_type; if constexpr (std::is_same_v, Ring>) desired_type = DataTypeCustomRingSerialization::nestedDataType(); else if constexpr (std::is_same_v, Polygon>) desired_type = DataTypeCustomPolygonSerialization::nestedDataType(); else if constexpr (std::is_same_v, MultiPolygon>) desired_type = DataTypeCustomMultiPolygonSerialization::nestedDataType(); else throw Exception("Unexpected Desired type.", ErrorCodes::LOGICAL_ERROR); if (!desired_type->equals(*column.type)) throw Exception(fmt::format("Expected type {} (MultiPolygon), but got {}", desired_type->getName(), column.type->getName()), ErrorCodes::BAD_ARGUMENTS); } template void checkColumnTypeOrThrow(const ColumnWithTypeAndName &); template void checkColumnTypeOrThrow(const ColumnWithTypeAndName &); template void checkColumnTypeOrThrow(const ColumnWithTypeAndName &); template void checkColumnTypeOrThrow(const ColumnWithTypeAndName &); template void checkColumnTypeOrThrow(const ColumnWithTypeAndName &); template void checkColumnTypeOrThrow(const ColumnWithTypeAndName &); }