Skip to content

Commit a191ff5

Browse files
committed
Check order of input files and warn if they are out of order
Osm2pgsql relies on the order nodes, then ways, then relations for correct functioning. Future versions will also need ids to be in order for efficiency and to allow merging and simplification of input files. This commits adds a warning output when the order is not correct. See #1167.
1 parent 9eb290b commit a191ff5

File tree

4 files changed

+124
-1
lines changed

4 files changed

+124
-1
lines changed

src/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11

22
set(osm2pgsql_lib_SOURCES
3+
check-order.cpp
34
db-copy.cpp
45
dependency-manager.cpp
56
expire-tiles.cpp

src/check-order.cpp

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
#include "check-order.hpp"
2+
#include "format.hpp"
3+
4+
#include <osmium/osm/relation.hpp>
5+
#include <osmium/osm/types.hpp>
6+
#include <osmium/osm/way.hpp>
7+
8+
void check_order_t::warning(char const *msg, osmid_t id)
9+
{
10+
fmt::print(stderr,
11+
"\nWARNING: {}: {}\n"
12+
" Unordered input files do not work correctly in all\n"
13+
" cases. Future versions of osm2pgsql will require\n"
14+
" ordered files. Use the 'sort' command of osmium tool\n"
15+
" to sort them first.\n\n",
16+
msg, id);
17+
m_issued_warning = true;
18+
}
19+
20+
void check_order_t::node(const osmium::Node &node)
21+
{
22+
if (m_issued_warning) {
23+
return;
24+
}
25+
26+
if (m_max_way_id > std::numeric_limits<osmid_t>::min()) {
27+
warning("Found a node after a way", node.id());
28+
}
29+
if (m_max_relation_id > std::numeric_limits<osmid_t>::min()) {
30+
warning("Found a node after a relation", node.id());
31+
}
32+
33+
if (m_max_node_id == node.id()) {
34+
warning("Node ID twice in input. Maybe you are using a history or "
35+
"non-simplified change file?",
36+
node.id());
37+
}
38+
if (node.id() < m_max_node_id) {
39+
warning("Node IDs out of order", node.id());
40+
}
41+
m_max_node_id = node.id();
42+
}
43+
44+
void check_order_t::way(const osmium::Way &way)
45+
{
46+
if (m_issued_warning) {
47+
return;
48+
}
49+
50+
if (m_max_relation_id > std::numeric_limits<osmid_t>::min()) {
51+
warning("Found a way after a relation", way.id());
52+
}
53+
54+
if (m_max_way_id == way.id()) {
55+
warning("Way ID twice in input. Maybe you are using a history or "
56+
"non-simplified change file?",
57+
way.id());
58+
}
59+
if (way.id() < m_max_way_id) {
60+
warning("Way IDs out of order", way.id());
61+
}
62+
m_max_way_id = way.id();
63+
}
64+
65+
void check_order_t::relation(const osmium::Relation &relation)
66+
{
67+
if (m_issued_warning) {
68+
return;
69+
}
70+
71+
if (m_max_relation_id == relation.id()) {
72+
warning("Relation ID twice in input. Maybe you are using a history or "
73+
"non-simplified change file?",
74+
relation.id());
75+
}
76+
if (relation.id() < m_max_relation_id) {
77+
warning("Relation IDs out of order", relation.id());
78+
}
79+
m_max_relation_id = relation.id();
80+
}

src/check-order.hpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#ifndef OSM2PGSQL_CHECK_ORDER_HPP
2+
#define OSM2PGSQL_CHECK_ORDER_HPP
3+
4+
#include "osmtypes.hpp"
5+
6+
#include <osmium/fwd.hpp>
7+
#include <osmium/handler.hpp>
8+
9+
#include <limits>
10+
11+
/**
12+
* Handler that can be used to check that an OSM file is ordered
13+
* correctly. Ordered in this case refers to the usual order in OSM
14+
* files: First nodes in the order of their IDs, then ways in the order
15+
* of their IDs, then relations in the order or their IDs.
16+
*
17+
* IDs have to be unique for each type. This check will fail for
18+
* history files.
19+
*/
20+
class check_order_t : public osmium::handler::Handler
21+
{
22+
23+
public:
24+
void node(const osmium::Node &node);
25+
26+
void way(const osmium::Way &way);
27+
28+
void relation(const osmium::Relation &relation);
29+
30+
private:
31+
void warning(char const *msg, osmid_t id);
32+
33+
osmid_t m_max_node_id = std::numeric_limits<osmid_t>::min();
34+
osmid_t m_max_way_id = std::numeric_limits<osmid_t>::min();
35+
osmid_t m_max_relation_id = std::numeric_limits<osmid_t>::min();
36+
37+
bool m_issued_warning = false;
38+
}; // class check_order_t
39+
40+
#endif // OSM2PGSQL_CHECK_ORDER_HPP

src/osmdata.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <osmium/io/any_input.hpp>
1212
#include <osmium/visitor.hpp>
1313

14+
#include "check-order.hpp"
1415
#include "db-copy.hpp"
1516
#include "format.hpp"
1617
#include "input-handler.hpp"
@@ -375,9 +376,10 @@ progress_display_t osmdata_t::process_file(osmium::io::File const &file,
375376
fmt::print(stderr, "Using {} parser.\n",
376377
osmium::io::as_string(file.format()));
377378

379+
check_order_t check_order{};
378380
input_handler_t handler{bbox, m_append, this};
379381
osmium::io::Reader reader{file};
380-
osmium::apply(reader, handler);
382+
osmium::apply(reader, check_order, handler);
381383
reader.close();
382384

383385
return handler.progress();

0 commit comments

Comments
 (0)