mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-12-04 21:42:39 +00:00
Implementing faster parsing of polygons 1.0
This commit is contained in:
parent
9a213f79ed
commit
c3ddbf8ab9
@ -11,7 +11,6 @@ namespace ErrorCodes
|
|||||||
{
|
{
|
||||||
extern const int TYPE_MISMATCH;
|
extern const int TYPE_MISMATCH;
|
||||||
extern const int BAD_ARGUMENTS;
|
extern const int BAD_ARGUMENTS;
|
||||||
extern const int LOGICAL_ERROR;
|
|
||||||
extern const int UNSUPPORTED_METHOD;
|
extern const int UNSUPPORTED_METHOD;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -419,7 +418,7 @@ void IPolygonDictionary::getItemsImpl(
|
|||||||
using ColType = std::conditional_t<std::is_same<AttributeType, String>::value, ColumnString, ColVecType>;
|
using ColType = std::conditional_t<std::is_same<AttributeType, String>::value, ColumnString, ColVecType>;
|
||||||
const auto column = typeid_cast<const ColType *>(attributes[attribute_ind].get());
|
const auto column = typeid_cast<const ColType *>(attributes[attribute_ind].get());
|
||||||
if (!column)
|
if (!column)
|
||||||
throw Exception{"An attribute should be a column of its type", ErrorCodes::LOGICAL_ERROR};
|
throw Exception{"An attribute should be a column of its type", ErrorCodes::BAD_ARGUMENTS};
|
||||||
for (const auto i : ext::range(0, points.size()))
|
for (const auto i : ext::range(0, points.size()))
|
||||||
{
|
{
|
||||||
size_t id = 0;
|
size_t id = 0;
|
||||||
@ -438,6 +437,17 @@ void IPolygonDictionary::getItemsImpl(
|
|||||||
query_count.fetch_add(points.size(), std::memory_order_relaxed);
|
query_count.fetch_add(points.size(), std::memory_order_relaxed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
|
inline void makeDifferences(IColumn::Offsets & values)
|
||||||
|
{
|
||||||
|
for (size_t i = 1; i < values.size(); ++i)
|
||||||
|
values[i] -= values[i - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void IPolygonDictionary::extractMultiPolygons(const ColumnPtr &column, std::vector<MultiPolygon> &dest) {
|
void IPolygonDictionary::extractMultiPolygons(const ColumnPtr &column, std::vector<MultiPolygon> &dest) {
|
||||||
const auto ptr_multi_polygons = typeid_cast<const ColumnArray*>(column.get());
|
const auto ptr_multi_polygons = typeid_cast<const ColumnArray*>(column.get());
|
||||||
if (!ptr_multi_polygons)
|
if (!ptr_multi_polygons)
|
||||||
@ -446,36 +456,57 @@ void IPolygonDictionary::extractMultiPolygons(const ColumnPtr &column, std::vect
|
|||||||
const auto ptr_polygons = typeid_cast<const ColumnArray*>(&ptr_multi_polygons->getData());
|
const auto ptr_polygons = typeid_cast<const ColumnArray*>(&ptr_multi_polygons->getData());
|
||||||
if (!ptr_polygons)
|
if (!ptr_polygons)
|
||||||
throw Exception{"Expected a column containing arrays of rings when reading polygons", ErrorCodes::TYPE_MISMATCH};
|
throw Exception{"Expected a column containing arrays of rings when reading polygons", ErrorCodes::TYPE_MISMATCH};
|
||||||
const auto & polygons = ptr_multi_polygons->getOffsets();
|
IColumn::Offsets & polygons = ptr_multi_polygons->getOffsets();
|
||||||
|
|
||||||
const auto ptr_rings = typeid_cast<const ColumnArray*>(&ptr_polygons->getData());
|
const auto ptr_rings = typeid_cast<const ColumnArray*>(&ptr_polygons->getData());
|
||||||
if (!ptr_rings)
|
if (!ptr_rings)
|
||||||
throw Exception{"Expected a column containing arrays of points when reading rings", ErrorCodes::TYPE_MISMATCH};
|
throw Exception{"Expected a column containing arrays of points when reading rings", ErrorCodes::TYPE_MISMATCH};
|
||||||
const auto & rings = ptr_polygons->getOffsets();
|
IColumn::Offsets & rings = ptr_polygons->getOffsets();
|
||||||
|
|
||||||
const auto ptr_points = typeid_cast<const ColumnArray*>(&ptr_rings->getData());
|
const auto ptr_points = typeid_cast<const ColumnArray*>(&ptr_rings->getData());
|
||||||
if (!ptr_points)
|
if (!ptr_points)
|
||||||
throw Exception{"Expected a column containing arrays of Float64s when reading points", ErrorCodes::TYPE_MISMATCH};
|
throw Exception{"Expected a column containing arrays of Float64s when reading points", ErrorCodes::TYPE_MISMATCH};
|
||||||
const auto & points = ptr_rings->getOffsets();
|
IColumn::Offsets & points = ptr_rings->getOffsets();
|
||||||
|
|
||||||
const auto ptr_coord = typeid_cast<const ColumnVector<Float64>*>(&ptr_points->getData());
|
const auto ptr_coord = typeid_cast<const ColumnVector<Float64>*>(&ptr_points->getData());
|
||||||
if (!ptr_coord)
|
if (!ptr_coord)
|
||||||
throw Exception{"Expected a column containing Float64s when reading coordinates", ErrorCodes::TYPE_MISMATCH};
|
throw Exception{"Expected a column containing Float64s when reading coordinates", ErrorCodes::TYPE_MISMATCH};
|
||||||
const auto & coordinates = ptr_points->getOffsets();
|
const auto & coordinates = ptr_points->getOffsets();
|
||||||
|
makeDifferences(polygons), makeDifferences(rings), makeDifferences(points);
|
||||||
IColumn::Offset point_offset = 0, ring_offset = 0, polygon_offset = 0;
|
IColumn::Offset point_offset = 0, ring_offset = 0, polygon_offset = 0;
|
||||||
dest.emplace_back();
|
dest.emplace_back();
|
||||||
for (size_t i = 0; i < coordinates.size(); ++i)
|
for (size_t i = 0; i < coordinates.size(); ++i)
|
||||||
{
|
{
|
||||||
if (polygons[polygon_offset] == 0)
|
|
||||||
{
|
|
||||||
dest.emplace_back();
|
|
||||||
++polygon_offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (coordinates[i] - (i == 0 ? 0 : coordinates[i - 1]) != DIM)
|
if (coordinates[i] - (i == 0 ? 0 : coordinates[i - 1]) != DIM)
|
||||||
throw Exception{"All points should be " + std::to_string(DIM) + "-dimensional", ErrorCodes::LOGICAL_ERROR};
|
throw Exception{"All points should be " + std::to_string(DIM) + "-dimensional", ErrorCodes::BAD_ARGUMENTS};
|
||||||
Point pt(ptr_coord->getElement(2 * i), ptr_coord->getElement(2 * i + 1));
|
if (points[point_offset] == 0)
|
||||||
|
{
|
||||||
|
++point_offset;
|
||||||
|
if (!dest.back().back().outer().empty())
|
||||||
|
dest.back().back().inners().emplace_back();
|
||||||
|
if (rings[ring_offset] == 0)
|
||||||
|
{
|
||||||
|
++ring_offset;
|
||||||
|
dest.back().emplace_back();
|
||||||
|
if (polygons[polygon_offset] == 0)
|
||||||
|
{
|
||||||
|
dest.emplace_back();
|
||||||
|
++polygon_offset;
|
||||||
|
}
|
||||||
|
if (polygon_offset == polygons.size())
|
||||||
|
throw Exception{"Incorrect polygon formatting", ErrorCodes::BAD_ARGUMENTS};
|
||||||
|
--polygons[polygon_offset];
|
||||||
|
}
|
||||||
|
if (ring_offset == rings.size())
|
||||||
|
throw Exception{"Incorrect polygon formatting", ErrorCodes::BAD_ARGUMENTS};
|
||||||
|
--rings[ring_offset];
|
||||||
|
}
|
||||||
|
if (point_offset == points.size())
|
||||||
|
throw Exception{"Incorrect polygon formatting", ErrorCodes::BAD_ARGUMENTS};
|
||||||
|
--points[point_offset];
|
||||||
|
auto & ring = (dest.back().back().inners().empty() ? dest.back().back().outer() : dest.back().back().inners().back());
|
||||||
|
ring.emplace_back(ptr_coord->getElement(2 * i), ptr_coord->getElement(2 * i + 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -485,7 +516,7 @@ IPolygonDictionary::Point IPolygonDictionary::fieldToPoint(const Field &field)
|
|||||||
{
|
{
|
||||||
auto coordinate_array = field.get<Array>();
|
auto coordinate_array = field.get<Array>();
|
||||||
if (coordinate_array.size() != DIM)
|
if (coordinate_array.size() != DIM)
|
||||||
throw Exception{"All points should be " + std::to_string(DIM) + "-dimensional", ErrorCodes::LOGICAL_ERROR};
|
throw Exception{"All points should be " + std::to_string(DIM) + "-dimensional", ErrorCodes::BAD_ARGUMENTS};
|
||||||
Float64 values[DIM];
|
Float64 values[DIM];
|
||||||
for (size_t i = 0; i < DIM; ++i)
|
for (size_t i = 0; i < DIM; ++i)
|
||||||
{
|
{
|
||||||
@ -506,7 +537,7 @@ IPolygonDictionary::Polygon IPolygonDictionary::fieldToPolygon(const Field & fie
|
|||||||
{
|
{
|
||||||
const auto & ring_array = field.get<Array>();
|
const auto & ring_array = field.get<Array>();
|
||||||
if (ring_array.empty())
|
if (ring_array.empty())
|
||||||
throw Exception{"Empty polygons are not allowed", ErrorCodes::LOGICAL_ERROR};
|
throw Exception{"Empty polygons are not allowed", ErrorCodes::BAD_ARGUMENTS};
|
||||||
result.inners().resize(ring_array.size() - 1);
|
result.inners().resize(ring_array.size() - 1);
|
||||||
if (ring_array[0].getType() != Field::Types::Array)
|
if (ring_array[0].getType() != Field::Types::Array)
|
||||||
throw Exception{"Outer polygon ring is not represented by an array", ErrorCodes::TYPE_MISMATCH};
|
throw Exception{"Outer polygon ring is not represented by an array", ErrorCodes::TYPE_MISMATCH};
|
||||||
@ -583,6 +614,9 @@ void registerDictionaryPolygon(DictionaryFactory & factory)
|
|||||||
const std::string & config_prefix,
|
const std::string & config_prefix,
|
||||||
DictionarySourcePtr source_ptr) -> DictionaryPtr
|
DictionarySourcePtr source_ptr) -> DictionaryPtr
|
||||||
{
|
{
|
||||||
|
const String database = config.getString(config_prefix + ".database", "");
|
||||||
|
const String name = config.getString(config_prefix + ".name");
|
||||||
|
|
||||||
// TODO: Check that there is only one key and it is of the correct type.
|
// TODO: Check that there is only one key and it is of the correct type.
|
||||||
if (dict_struct.range_min || dict_struct.range_max)
|
if (dict_struct.range_min || dict_struct.range_max)
|
||||||
throw Exception{name
|
throw Exception{name
|
||||||
@ -590,8 +624,6 @@ void registerDictionaryPolygon(DictionaryFactory & factory)
|
|||||||
"for a dictionary of layout 'range_hashed'",
|
"for a dictionary of layout 'range_hashed'",
|
||||||
ErrorCodes::BAD_ARGUMENTS};
|
ErrorCodes::BAD_ARGUMENTS};
|
||||||
|
|
||||||
const String database = config.getString(config_prefix + ".database", "");
|
|
||||||
const String name = config.getString(config_prefix + ".name");
|
|
||||||
const DictionaryLifetime dict_lifetime{config, config_prefix + ".lifetime"};
|
const DictionaryLifetime dict_lifetime{config, config_prefix + ".lifetime"};
|
||||||
return std::make_unique<SimplePolygonDictionary>(database, name, dict_struct, std::move(source_ptr), dict_lifetime);
|
return std::make_unique<SimplePolygonDictionary>(database, name, dict_struct, std::move(source_ptr), dict_lifetime);
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user