Skip to content

Commit 1555407

Browse files
committed
Make clustering by geometry optional in flex output
Set table option cluster='no' to disable it. The default is cluster='auto'. As before this does clustering with the "best" method depending on the PostgreSQL version. Other values might be available in the future. (If the table doesn't have a geometry column, there is no clustering, of course.) See #27
1 parent e99f334 commit 1555407

File tree

8 files changed

+114
-9
lines changed

8 files changed

+114
-9
lines changed

src/flex-table.cpp

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ void table_connection_t::stop(bool updateable, bool append)
199199
return;
200200
}
201201

202-
if (table().has_geom_column()) {
202+
if (table().cluster_by_geom()) {
203203
if (table().geom_column().needs_isvalid()) {
204204
drop_geom_check_trigger(m_db_connection.get(), table().schema(),
205205
table().name());
@@ -246,6 +246,14 @@ void table_connection_t::stop(bool updateable, bool append)
246246
table().full_tmp_name(), table().name()));
247247
m_id_index_created = false;
248248

249+
if (updateable && table().geom_column().needs_isvalid()) {
250+
create_geom_check_trigger(m_db_connection.get(), table().schema(),
251+
table().name(),
252+
table().geom_column().name());
253+
}
254+
}
255+
256+
if (table().has_geom_column()) {
249257
log_info("Creating geometry index on table '{}'...", table().name());
250258

251259
// Use fillfactor 100 for un-updateable imports
@@ -258,13 +266,6 @@ void table_connection_t::stop(bool updateable, bool append)
258266

259267
if (updateable && table().has_id_column()) {
260268
create_id_index();
261-
262-
if (table().has_geom_column() &&
263-
table().geom_column().needs_isvalid()) {
264-
create_geom_check_trigger(m_db_connection.get(), table().schema(),
265-
table().name(),
266-
table().geom_column().name());
267-
}
268269
}
269270

270271
log_info("Analyzing table '{}'...", table().name());

src/flex-table.hpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,11 @@ class flex_table_t
4848

4949
std::string const &schema() const noexcept { return m_schema; }
5050

51+
bool cluster_by_geom() const noexcept
52+
{
53+
return has_geom_column() && m_cluster_by_geom;
54+
}
55+
5156
std::string const &data_tablespace() const noexcept
5257
{
5358
return m_data_tablespace;
@@ -60,6 +65,11 @@ class flex_table_t
6065

6166
void set_schema(std::string const &schema) noexcept { m_schema = schema; }
6267

68+
void set_cluster_by_geom(bool cluster) noexcept
69+
{
70+
m_cluster_by_geom = cluster;
71+
}
72+
6373
void set_data_tablespace(std::string const &tablespace) noexcept
6474
{
6575
m_data_tablespace = tablespace;
@@ -211,6 +221,9 @@ class flex_table_t
211221
*/
212222
osmium::item_type m_id_type = osmium::item_type::undefined;
213223

224+
/// Cluster the table by geometry.
225+
bool m_cluster_by_geom = true;
226+
214227
}; // class flex_table_t
215228

216229
class table_connection_t

src/output-flex.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ TRAMPOLINE(app_define_table, define_table)
6969
TRAMPOLINE(app_get_bbox, get_bbox)
7070
TRAMPOLINE(table_name, name)
7171
TRAMPOLINE(table_schema, schema)
72+
TRAMPOLINE(table_cluster, cluster)
7273
TRAMPOLINE(table_add_row, add_row)
7374
TRAMPOLINE(table_columns, columns)
7475
TRAMPOLINE(table_tostring, __tostring)
@@ -771,6 +772,28 @@ flex_table_t &output_flex_t::create_flex_table()
771772
}
772773
lua_pop(lua_state(), 1);
773774

775+
// optional "cluster" field
776+
lua_getfield(lua_state(), -1, "cluster");
777+
int const cluster_type = lua_type(lua_state(), -1);
778+
if (cluster_type == LUA_TSTRING) {
779+
std::string const cluster = lua_tostring(lua_state(), -1);
780+
if (cluster == "auto") {
781+
new_table.set_cluster_by_geom(true);
782+
} else if (cluster == "no") {
783+
new_table.set_cluster_by_geom(false);
784+
} else {
785+
throw std::runtime_error{
786+
"Unknown value '{}' for 'cluster' table option"
787+
" (use 'auto' or 'no')."_format(cluster)};
788+
}
789+
} else if (cluster_type == LUA_TNIL) {
790+
// ignore
791+
} else {
792+
throw std::runtime_error{
793+
"Unknown value for 'cluster' table option: Must be string."};
794+
}
795+
lua_pop(lua_state(), 1);
796+
774797
// optional "data_tablespace" field
775798
lua_getfield(lua_state(), -1, "data_tablespace");
776799
if (lua_isstring(lua_state(), -1)) {
@@ -1058,6 +1081,13 @@ int output_flex_t::table_schema()
10581081
return 1;
10591082
}
10601083

1084+
int output_flex_t::table_cluster()
1085+
{
1086+
auto const &table = get_table_from_param();
1087+
lua_pushboolean(lua_state(), table.cluster_by_geom());
1088+
return 1;
1089+
}
1090+
10611091
static std::unique_ptr<geom_transform_t>
10621092
get_transform(lua_State *lua_state, flex_table_column_t const &column)
10631093
{
@@ -1615,6 +1645,7 @@ void output_flex_t::init_lua(std::string const &filename)
16151645
luaX_add_table_func(lua_state(), "add_row", lua_trampoline_table_add_row);
16161646
luaX_add_table_func(lua_state(), "name", lua_trampoline_table_name);
16171647
luaX_add_table_func(lua_state(), "schema", lua_trampoline_table_schema);
1648+
luaX_add_table_func(lua_state(), "cluster", lua_trampoline_table_cluster);
16181649
luaX_add_table_func(lua_state(), "columns", lua_trampoline_table_columns);
16191650

16201651
// Clean up stack

src/output-flex.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ class output_flex_t : public output_t
159159
int table_add_row();
160160
int table_name();
161161
int table_schema();
162+
int table_cluster();
162163
int table_columns();
163164

164165
private:

tests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ if (HAVE_LUA)
7373
set_test(test-output-flex-area)
7474
set_test(test-output-flex-attr)
7575
set_test(test-output-flex-bbox)
76+
set_test(test-output-flex-cluster)
7677
set_test(test-output-flex-invalid-geom)
7778
set_test(test-output-flex-line)
7879
set_test(test-output-flex-lua-fail)

tests/data/test_output_flex.lua

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ tables.line = osm2pgsql.define_table{
1313
{ column = 'tags', type = 'hstore' },
1414
{ column = 'name', type = 'text' },
1515
{ column = 'geom', type = 'linestring' },
16-
}
16+
},
17+
cluster = 'auto'
1718
}
1819

1920
tables.polygon = osm2pgsql.define_table{
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
2+
local dtable = osm2pgsql.define_node_table('osm2pgsql_test_point', {
3+
{ column = 'tags', type = 'hstore' },
4+
{ column = 'geom', type = 'point' },
5+
}, { cluster = 'no' })
6+
7+
function is_empty(some_table)
8+
return next(some_table) == nil
9+
end
10+
11+
function clean_tags(tags)
12+
tags.odbl = nil
13+
tags.created_by = nil
14+
tags.source = nil
15+
tags['source:ref'] = nil
16+
tags['source:name'] = nil
17+
end
18+
19+
function osm2pgsql.process_node(data)
20+
clean_tags(data.tags)
21+
if is_empty(data.tags) then
22+
return
23+
end
24+
25+
dtable:add_row({
26+
tags = data.tags
27+
})
28+
end
29+

tests/test-output-flex-cluster.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#include <catch.hpp>
2+
3+
#include "common-import.hpp"
4+
#include "common-options.hpp"
5+
6+
static testing::db::import_t db;
7+
8+
static char const *const conf_file = "test_output_flex_nocluster.lua";
9+
static char const *const data_file = "liechtenstein-2013-08-03.osm.pbf";
10+
11+
TEST_CASE("non-slim without clustering")
12+
{
13+
REQUIRE_NOTHROW(db.run_file(testing::opt_t().flex(conf_file), data_file));
14+
15+
auto conn = db.db().connect();
16+
17+
CHECK(1362 == conn.get_count("osm2pgsql_test_point"));
18+
}
19+
20+
TEST_CASE("slim without clustering")
21+
{
22+
REQUIRE_NOTHROW(
23+
db.run_file(testing::opt_t().slim().flex(conf_file), data_file));
24+
25+
auto conn = db.db().connect();
26+
27+
CHECK(1362 == conn.get_count("osm2pgsql_test_point"));
28+
}

0 commit comments

Comments
 (0)