diff --git a/src/output-flex.cpp b/src/output-flex.cpp index 33cc87987..b5f0b631c 100644 --- a/src/output-flex.cpp +++ b/src/output-flex.cpp @@ -494,6 +494,32 @@ static void write_json(json_writer_type *writer, lua_State *lua_state, } } +static bool is_compatible(geom::geometry_t const &geom, + table_column_type type) noexcept +{ + switch (type) { + case table_column_type::geometry: + return true; + case table_column_type::point: + return geom.is_point(); + case table_column_type::linestring: + return geom.is_linestring(); + case table_column_type::polygon: + return geom.is_polygon(); + case table_column_type::multipoint: + return geom.is_point() || geom.is_multipoint(); + case table_column_type::multilinestring: + return geom.is_linestring() || geom.is_multilinestring(); + case table_column_type::multipolygon: + return geom.is_polygon() || geom.is_multipolygon(); + case table_column_type::geometrycollection: + return geom.is_collection(); + default: + break; + } + return false; +} + void output_flex_t::write_column( db_copy_mgr_t *copy_mgr, flex_table_column_t const &column) @@ -672,11 +698,22 @@ void output_flex_t::write_column( if (ltype == LUA_TUSERDATA) { auto const *const geom = unpack_geometry(lua_state(), -1); if (geom && !geom->is_null()) { + auto const type = column.type(); + if (!is_compatible(*geom, type)) { + throw std::runtime_error{ + "Geometry data for geometry column '{}'" + " has the wrong type ({})."_format( + column.name(), geometry_type(*geom))}; + } + bool const wrap_multi = + (type == table_column_type::multipoint || + type == table_column_type::multilinestring || + type == table_column_type::multipolygon); if (geom->srid() == column.srid()) { // OSM id not available here, so use dummy 0, it is used // for debug messages only anyway. m_expire.from_geometry(*geom, 0); - copy_mgr->add_hex_geom(geom_to_ewkb(*geom)); + copy_mgr->add_hex_geom(geom_to_ewkb(*geom, wrap_multi)); } else { auto const proj = reprojection::create_projection(column.srid()); @@ -684,7 +721,7 @@ void output_flex_t::write_column( // OSM id not available here, so use dummy 0, it is used // for debug messages only anyway. m_expire.from_geometry(tgeom, 0); - copy_mgr->add_hex_geom(geom_to_ewkb(tgeom)); + copy_mgr->add_hex_geom(geom_to_ewkb(tgeom, wrap_multi)); } } else { write_null(copy_mgr, column); diff --git a/tests/bdd/flex/geometry-linestring.feature b/tests/bdd/flex/geometry-linestring.feature new file mode 100644 index 000000000..ec3526c68 --- /dev/null +++ b/tests/bdd/flex/geometry-linestring.feature @@ -0,0 +1,67 @@ +Feature: Creating linestring features from way + + Scenario: + Given the grid + | 1 | 2 | | + | 4 | | 3 | + | | 5 | | + And the OSM data + """ + w20 Thighway=motorway Nn1,n2,n3 + w21 Thighway=motorway Nn4,n5 + """ + And the lua style + """ + local lines = osm2pgsql.define_way_table('osm2pgsql_test_lines', { + { column = 'sgeom', type = 'linestring', projection = 4326 }, + { column = 'mgeom', type = 'multilinestring', projection = 4326 }, + { column = 'xgeom', type = 'multilinestring', projection = 4326 }, + }) + + function osm2pgsql.process_way(object) + if object.tags.highway == 'motorway' then + lines:insert({ + sgeom = object:as_linestring(), + mgeom = object:as_multilinestring(), + xgeom = object:as_linestring() + }) + end + end + + """ + When running osm2pgsql flex + + Then table osm2pgsql_test_lines contains exactly + | way_id | ST_AsText(sgeom) | ST_AsText(ST_GeometryN(mgeom, 1)) | ST_AsText(ST_GeometryN(xgeom, 1)) | + | 20 | 1, 2, 3 | 1, 2, 3 | 1, 2, 3 | + | 21 | 4, 5 | 4, 5 | 4, 5 | + + Scenario: + Given the grid + | 1 | 2 | + And the OSM data + """ + w20 Thighway=motorway Nn1,n2 + """ + And the lua style + """ + local lines = osm2pgsql.define_way_table('osm2pgsql_test_lines', { + { column = 'geom', type = 'polygon', projection = 4326 }, + }) + + function osm2pgsql.process_way(object) + if object.tags.highway == 'motorway' then + lines:insert({ + geom = object:as_linestring(), + }) + end + end + + """ + Then running osm2pgsql flex fails + + And the error output contains + """ + Geometry data for geometry column 'geom' has the wrong type (LINESTRING). + """ +