ClickHouse/src/Functions/geometryConverters.cpp

105 lines
3.3 KiB
C++
Raw Normal View History

2020-06-14 17:04:10 +00:00
#include <Functions/geometryConverters.h>
2020-06-07 16:47:56 +00:00
#include <DataTypes/DataTypeCustomGeo.h>
2020-06-07 12:33:49 +00:00
#include <common/logger_useful.h>
2020-06-07 12:33:49 +00:00
2020-06-07 16:47:56 +00:00
namespace DB {
2020-06-07 13:42:09 +00:00
namespace {
2020-06-07 14:58:34 +00:00
size_t getArrayDepth(DataTypePtr data_type, size_t max_depth)
2020-06-07 13:42:09 +00:00
{
size_t depth = 0;
2020-06-07 16:47:56 +00:00
while (data_type && isArray(data_type) && depth != max_depth + 1)
2020-06-07 13:42:09 +00:00
{
2020-06-07 16:47:56 +00:00
depth++;
2020-06-07 13:42:09 +00:00
data_type = static_cast<const DataTypeArray &>(*data_type).getNestedType();
}
2020-06-07 16:47:56 +00:00
return depth;
2020-06-07 13:42:09 +00:00
}
2021-01-18 23:51:34 +00:00
template <typename Geometry>
class ContainerCreator : public boost::static_visitor<Geometry>
2020-06-07 16:04:35 +00:00
{
public:
template <class T>
2021-01-18 23:51:34 +00:00
Geometry operator()(const T & parser) const
2020-06-07 16:04:35 +00:00
{
return parser.createContainer();
}
};
2021-01-19 14:52:53 +00:00
template <typename Point>
2020-06-07 16:04:35 +00:00
class Getter : public boost::static_visitor<void>
{
public:
2021-01-19 14:52:53 +00:00
constexpr Getter(Geometry<Point> & container_, size_t i_)
2020-06-07 16:04:35 +00:00
: container(container_)
, i(i_)
{}
template <class T>
void operator()(const T & parser) const
{
parser.get(container, i);
}
private:
2021-01-19 14:52:53 +00:00
Geometry<Point> & container;
2020-06-07 16:04:35 +00:00
size_t i;
};
2020-06-07 18:26:18 +00:00
template <class DataType, class Parser>
Parser makeParser(const ColumnWithTypeAndName & col)
2020-06-07 16:47:56 +00:00
{
2020-06-07 17:28:05 +00:00
auto wanted_data_type = DataType::nestedDataType();
2020-06-14 17:04:10 +00:00
ColumnPtr casted = castColumn(col, DataType::nestedDataType());
2020-06-07 16:47:56 +00:00
if (!casted)
{
throw Exception("Failed to cast " + col.type->getName() + " to " + wanted_data_type->getName(), ErrorCodes::ILLEGAL_COLUMN);
}
2020-06-14 17:04:10 +00:00
return Parser(std::move(casted));
2020-06-07 18:26:18 +00:00
}
2020-06-07 16:47:56 +00:00
}
2021-01-19 14:52:53 +00:00
template <typename Point>
Geometry<Point> createContainer(const GeometryFromColumnParser<Point> & parser)
2020-06-07 12:33:49 +00:00
{
2021-01-19 14:52:53 +00:00
static ContainerCreator<Geometry<Point>> creator;
2021-01-18 23:51:34 +00:00
return boost::apply_visitor(creator, parser);
}
2021-01-19 14:52:53 +00:00
template <typename Point>
void get(const GeometryFromColumnParser<Point> & parser, Geometry<Point> & container, size_t i)
2021-01-18 23:51:34 +00:00
{
2021-01-19 14:52:53 +00:00
boost::apply_visitor(Getter<Point>(container, i), parser);
2021-01-18 23:51:34 +00:00
}
2021-01-19 14:52:53 +00:00
template <typename Point>
GeometryFromColumnParser<Point> makeGeometryFromColumnParser(const ColumnWithTypeAndName & col)
2021-01-18 23:51:34 +00:00
{
switch (getArrayDepth(col.type, 3))
{
2021-01-19 14:52:53 +00:00
case 0: return makeParser<DataTypeCustomPointSerialization, PointFromColumnParser<Point>>(col);
case 1: return makeParser<DataTypeCustomRingSerialization, RingFromColumnParser<Point>>(col);
case 2: return makeParser<DataTypeCustomPolygonSerialization, PolygonFromColumnParser<Point>>(col);
case 3: return makeParser<DataTypeCustomMultiPolygonSerialization, MultiPolygonFromColumnParser<Point>>(col);
2020-06-07 14:28:46 +00:00
default: throw Exception("Cannot parse geometry from column with type " + col.type->getName()
+ ", array depth is too big", ErrorCodes::ILLEGAL_COLUMN);
2020-06-07 13:42:09 +00:00
}
2020-06-07 12:33:49 +00:00
}
2021-01-19 14:52:53 +00:00
/// Explicit instantiations to avoid linker errors.
template Geometry<CartesianPoint> createContainer(const GeometryFromColumnParser<CartesianPoint> &);
template Geometry<GeographicPoint> createContainer(const GeometryFromColumnParser<GeographicPoint> &);
template void get(const GeometryFromColumnParser<CartesianPoint> & parser, Geometry<CartesianPoint> & container, size_t i);
template void get(const GeometryFromColumnParser<GeographicPoint> & parser, Geometry<GeographicPoint> & container, size_t i);
template GeometryFromColumnParser<CartesianPoint> makeGeometryFromColumnParser(const ColumnWithTypeAndName & col);
template GeometryFromColumnParser<GeographicPoint> makeGeometryFromColumnParser(const ColumnWithTypeAndName & col);
2020-06-07 16:04:35 +00:00
2020-06-07 12:33:49 +00:00
}