Skip to content

Commit 8d1a55e

Browse files
committed
Fix problem in slim mode with two-state processing of nodes
In two-stage processing when getting nodes from the middle we are running the same SQL query as when getting the node locations. But that doesn't work. We need more information, the tags (and possibly the attributes). This fixes this by running a different prepared query in this case. Fixes #2298
1 parent f900e2c commit 8d1a55e

File tree

3 files changed

+264
-4
lines changed

3 files changed

+264
-4
lines changed

src/middle-pgsql.cpp

+14-4
Original file line numberDiff line numberDiff line change
@@ -522,7 +522,7 @@ std::size_t middle_query_pgsql_t::get_way_node_locations_flatnodes(
522522

523523
osmium::Location middle_query_pgsql_t::get_node_location_db(osmid_t id) const
524524
{
525-
auto const res = m_db_connection.exec_prepared("get_node", id);
525+
auto const res = m_db_connection.exec_prepared("get_node_location", id);
526526
if (res.num_tuples() == 0) {
527527
return osmium::Location{};
528528
}
@@ -729,11 +729,14 @@ void build_node(osmid_t id, pg_result_t const &res, int res_num, int offset,
729729
{
730730
osmium::builder::NodeBuilder builder{*buffer};
731731
builder.set_id(id);
732+
builder.set_location(osmium::Location{
733+
(int)std::strtol(res.get_value(res_num, offset + 0), nullptr, 10),
734+
(int)std::strtol(res.get_value(res_num, offset + 1), nullptr, 10)});
732735

733736
if (with_attributes) {
734-
set_attributes_on_builder(&builder, res, res_num, offset);
737+
set_attributes_on_builder(&builder, res, res_num, offset + 3);
735738
}
736-
pgsql_parse_json_tags(res.get_value(res_num, offset + 1), buffer, &builder);
739+
pgsql_parse_json_tags(res.get_value(res_num, offset + 2), buffer, &builder);
737740
}
738741

739742
/**
@@ -1261,7 +1264,7 @@ middle_pgsql_t::get_query_instance()
12611264
m_store_options);
12621265

12631266
if (m_store_options.nodes) {
1264-
mid->prepare("get_node",
1267+
mid->prepare("get_node_location",
12651268
render_template(
12661269
"SELECT id, lon, lat FROM {schema}\"{prefix}_nodes\""
12671270
" WHERE id = $1::int8"));
@@ -1270,6 +1273,13 @@ middle_pgsql_t::get_query_instance()
12701273
render_template(
12711274
"SELECT id, lon, lat FROM {schema}\"{prefix}_nodes\""
12721275
" WHERE id = ANY($1::int8[])"));
1276+
1277+
mid->prepare(
1278+
"get_node",
1279+
render_template("SELECT lon, lat, tags{attribute_columns_use}"
1280+
" FROM {schema}\"{prefix}_nodes\" o"
1281+
" {users_table_access}"
1282+
" WHERE o.id = $1::int8"));
12731283
}
12741284

12751285
mid->prepare("get_way",

tests/bdd/flex/node-add.feature

+164
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
Feature: Adding nodes to a flex database
2+
3+
Background:
4+
Given the style file 'test_output_flex_node.lua'
5+
6+
And the OSM data
7+
"""
8+
n11 v1 dV Tt1=yes x1 y1
9+
n12 v1 dV Tt2=yes x2 y2
10+
n13 v1 dV Ttboth=yes x3 y3
11+
n14 v1 dV Ttboth=yes x4 y4
12+
r30 v1 dV Tt=ag Mn11@,n12@mark,n13@,n14@mark
13+
"""
14+
When running osm2pgsql flex with parameters
15+
| --slim |
16+
17+
Then table osm2pgsql_test_t1 contains exactly
18+
| node_id |
19+
| 11 |
20+
Then table osm2pgsql_test_t2 contains exactly
21+
| node_id |
22+
| 12 |
23+
Then table osm2pgsql_test_tboth contains exactly
24+
| node_id |
25+
| 13 |
26+
| 14 |
27+
28+
29+
Scenario: node is not relevant
30+
Given an empty grid
31+
And the OSM data
32+
"""
33+
n10 v1 dV Tt=ag x0 y0
34+
r30 v2 dV Tt=ag Mn10@,n11@,n12@mark,n13@,n14@mark
35+
"""
36+
When running osm2pgsql flex with parameters
37+
| --slim | -a |
38+
39+
Then table osm2pgsql_test_t1 contains exactly
40+
| node_id |
41+
| 11 |
42+
Then table osm2pgsql_test_t2 contains exactly
43+
| node_id |
44+
| 12 |
45+
Then table osm2pgsql_test_tboth contains exactly
46+
| node_id |
47+
| 13 |
48+
| 14 |
49+
50+
51+
Scenario: add to t1
52+
Given an empty grid
53+
And the OSM data
54+
"""
55+
n10 v1 dV Tt1=yes x0 y0
56+
r30 v2 dV Tt=ag Mn10@,n11@,n12@mark,n13@,n14@mark
57+
"""
58+
When running osm2pgsql flex with parameters
59+
| --slim | -a |
60+
61+
Then table osm2pgsql_test_t1 contains exactly
62+
| node_id |
63+
| 10 |
64+
| 11 |
65+
Then table osm2pgsql_test_t2 contains exactly
66+
| node_id |
67+
| 12 |
68+
Then table osm2pgsql_test_tboth contains exactly
69+
| node_id |
70+
| 13 |
71+
| 14 |
72+
73+
74+
Scenario: add to t2
75+
Given an empty grid
76+
And the OSM data
77+
"""
78+
n10 v1 dV Tt2=yes x0 y0
79+
r30 v2 dV Tt=ag Mn10@mark,n11@,n12@mark,n13@,n14@mark
80+
"""
81+
When running osm2pgsql flex with parameters
82+
| --slim | -a |
83+
84+
Then table osm2pgsql_test_t1 contains exactly
85+
| node_id |
86+
| 11 |
87+
Then table osm2pgsql_test_t2 contains exactly
88+
| node_id | rel_ids |
89+
| 10 | {30} |
90+
| 12 | {30} |
91+
Then table osm2pgsql_test_tboth contains exactly
92+
| node_id |
93+
| 13 |
94+
| 14 |
95+
96+
97+
Scenario: add to t1 and t2
98+
Given an empty grid
99+
And the OSM data
100+
"""
101+
n10 v1 dV Tt1=yes,t2=yes x0 y0
102+
r30 v2 dV Tt=ag Mn10@mark,n11@,n12@mark,n13@,n14@mark
103+
"""
104+
When running osm2pgsql flex with parameters
105+
| --slim | -a |
106+
107+
Then table osm2pgsql_test_t1 contains exactly
108+
| node_id |
109+
| 10 |
110+
| 11 |
111+
Then table osm2pgsql_test_t2 contains exactly
112+
| node_id | rel_ids |
113+
| 10 | {30} |
114+
| 12 | {30} |
115+
Then table osm2pgsql_test_tboth contains exactly
116+
| node_id |
117+
| 13 |
118+
| 14 |
119+
120+
121+
Scenario: add to tboth (only stage1)
122+
Given an empty grid
123+
And the OSM data
124+
"""
125+
n10 v1 dV Ttboth=yes x0 y0
126+
r30 v2 dV Tt=ag Mn10@,n11@,n12@mark,n13@,n14@mark
127+
"""
128+
When running osm2pgsql flex with parameters
129+
| --slim | -a |
130+
131+
Then table osm2pgsql_test_t1 contains exactly
132+
| node_id |
133+
| 11 |
134+
Then table osm2pgsql_test_t2 contains exactly
135+
| node_id |
136+
| 12 |
137+
Then table osm2pgsql_test_tboth contains exactly
138+
| node_id | rel_ids |
139+
| 10 | NULL |
140+
| 13 | NULL |
141+
| 14 | {30} |
142+
143+
144+
Scenario: add to tboth (stage1 and stage2)
145+
Given an empty grid
146+
And the OSM data
147+
"""
148+
n10 v1 dV Ttboth=yes x0 y0
149+
r30 v2 dV Tt=ag Mn10@mark,n11@,n12@mark,n13@,n14@mark
150+
"""
151+
When running osm2pgsql flex with parameters
152+
| --slim | -a |
153+
154+
Then table osm2pgsql_test_t1 contains exactly
155+
| node_id |
156+
| 11 |
157+
Then table osm2pgsql_test_t2 contains exactly
158+
| node_id |
159+
| 12 |
160+
Then table osm2pgsql_test_tboth contains exactly
161+
| node_id | rel_ids |
162+
| 10 | {30} |
163+
| 13 | NULL |
164+
| 14 | {30} |

tests/data/test_output_flex_node.lua

+86
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
2+
local tables = {}
3+
4+
tables.t1 = osm2pgsql.define_node_table('osm2pgsql_test_t1', {
5+
{ column = 'tags', type = 'hstore' },
6+
{ column = 'geom', type = 'point', not_null = true },
7+
})
8+
9+
tables.t2 = osm2pgsql.define_node_table('osm2pgsql_test_t2', {
10+
{ column = 'tags', type = 'hstore' },
11+
{ column = 'rel_ids', type = 'text' },
12+
{ column = 'geom', type = 'point', not_null = true },
13+
})
14+
15+
tables.tboth = osm2pgsql.define_node_table('osm2pgsql_test_tboth', {
16+
{ column = 'tags', type = 'hstore' },
17+
{ column = 'rel_ids', type = 'text' },
18+
{ column = 'geom', type = 'point', not_null = true },
19+
})
20+
21+
local n2r = {}
22+
23+
local function get_ids(data)
24+
if data then
25+
local ids = {}
26+
for rel_id, _ in pairs(data) do
27+
ids[#ids + 1] = rel_id
28+
end
29+
table.sort(ids)
30+
return '{' .. table.concat(ids, ',') .. '}'
31+
end
32+
end
33+
34+
function osm2pgsql.process_node(object)
35+
if object.tags.t1 then
36+
tables.t1:insert{
37+
tags = object.tags,
38+
geom = object:as_point()
39+
}
40+
end
41+
42+
if osm2pgsql.stage == 2 and object.tags.t2 then
43+
local ids = get_ids(n2r[object.id])
44+
if ids then
45+
tables.t2:insert{
46+
rel_ids = ids,
47+
geom = object:as_point()
48+
}
49+
end
50+
end
51+
52+
if object.tags.tboth then
53+
local ids = get_ids(n2r[object.id])
54+
tables.tboth:insert{
55+
tags = object.tags,
56+
rel_ids = ids,
57+
geom = object:as_point()
58+
}
59+
end
60+
end
61+
62+
local function node_member_ids(relation)
63+
local ids = {}
64+
for _, member in ipairs(relation.members) do
65+
if member.type == 'n' and member.role == 'mark' then
66+
ids[#ids + 1] = member.ref
67+
end
68+
end
69+
return ids
70+
end
71+
72+
function osm2pgsql.select_relation_members(relation)
73+
return { nodes = node_member_ids(relation) }
74+
end
75+
76+
function osm2pgsql.process_relation(object)
77+
for _, member in ipairs(object.members) do
78+
if member.type == 'n' and member.role == 'mark' then
79+
if not n2r[member.ref] then
80+
n2r[member.ref] = {}
81+
end
82+
n2r[member.ref][object.id] = true
83+
end
84+
end
85+
end
86+

0 commit comments

Comments
 (0)