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
|
|
|
|
2020-06-21 17:59:18 +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-21 17:59:18 +00:00
|
|
|
|
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-18 23:51:34 +00:00
|
|
|
template <typename Geometry>
|
2020-06-07 16:04:35 +00:00
|
|
|
class Getter : public boost::static_visitor<void>
|
|
|
|
{
|
|
|
|
public:
|
2021-01-18 23:51:34 +00:00
|
|
|
constexpr Getter(Geometry & 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-18 23:51:34 +00:00
|
|
|
Geometry & 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-18 23:51:34 +00:00
|
|
|
CartesianGeometryFromColumnParser makeCartesianGeometryFromColumnParser(const ColumnWithTypeAndName & col)
|
2020-06-07 12:33:49 +00:00
|
|
|
{
|
2021-01-18 23:51:34 +00:00
|
|
|
switch (getArrayDepth(col.type, 3))
|
|
|
|
{
|
|
|
|
case 0: return makeParser<DataTypeCustomPointSerialization, PointFromColumnParser<CartesianPoint>>(col);
|
|
|
|
case 1: return makeParser<DataTypeCustomRingSerialization, CartesianRingFromColumnParser>(col);
|
|
|
|
case 2: return makeParser<DataTypeCustomPolygonSerialization, CartesianPolygonFromColumnParser>(col);
|
|
|
|
case 3: return makeParser<DataTypeCustomMultiPolygonSerialization, CartesianMultiPolygonFromColumnParser>(col);
|
|
|
|
default: throw Exception("Cannot parse geometry from column with type " + col.type->getName()
|
|
|
|
+ ", array depth is too big", ErrorCodes::ILLEGAL_COLUMN);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
CartesianGeometry createContainer(const CartesianGeometryFromColumnParser & parser)
|
|
|
|
{
|
|
|
|
static ContainerCreator<CartesianGeometry> creator;
|
|
|
|
return boost::apply_visitor(creator, parser);
|
|
|
|
}
|
|
|
|
|
|
|
|
void get(const CartesianGeometryFromColumnParser & parser, CartesianGeometry & container, size_t i)
|
|
|
|
{
|
|
|
|
boost::apply_visitor(Getter(container, i), parser);
|
|
|
|
}
|
|
|
|
|
|
|
|
GeographicGeometryFromColumnParser makeGeographicGeometryFromColumnParser(const ColumnWithTypeAndName & col)
|
|
|
|
{
|
|
|
|
switch (getArrayDepth(col.type, 3))
|
|
|
|
{
|
|
|
|
case 0: return makeParser<DataTypeCustomPointSerialization, PointFromColumnParser<GeographicPoint>>(col);
|
|
|
|
case 1: return makeParser<DataTypeCustomRingSerialization, GeographicRingFromColumnParser>(col);
|
|
|
|
case 2: return makeParser<DataTypeCustomPolygonSerialization, GeographicPolygonFromColumnParser>(col);
|
|
|
|
case 3: return makeParser<DataTypeCustomMultiPolygonSerialization, GeographicMultiPolygonFromColumnParser>(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-18 23:51:34 +00:00
|
|
|
GeographicGeometry createContainer(const GeographicGeometryFromColumnParser & parser)
|
2020-06-07 16:04:35 +00:00
|
|
|
{
|
2021-01-18 23:51:34 +00:00
|
|
|
static ContainerCreator<GeographicGeometry> creator;
|
2020-06-07 16:04:35 +00:00
|
|
|
return boost::apply_visitor(creator, parser);
|
|
|
|
}
|
|
|
|
|
2021-01-18 23:51:34 +00:00
|
|
|
void get(const GeographicGeometryFromColumnParser & parser, GeographicGeometry & container, size_t i)
|
2020-06-07 16:04:35 +00:00
|
|
|
{
|
|
|
|
boost::apply_visitor(Getter(container, i), parser);
|
|
|
|
}
|
|
|
|
|
2020-06-07 12:33:49 +00:00
|
|
|
}
|