Skip to content

Commit facdb98

Browse files
committed
Allow table inserts without context object
So far an `insert()` into a table was only allowed in the node, way and relation processing functions, i.e. those function with a "context object". That makes sense in so far as the id column(s) can only been filled magically if there is a context object. But osm2pgsql has allowed tables without id column(s) for a long time. These tables can now be filled from any processing function, for instance in the `after_*` callbacks. It is still not possible to call `insert()` from the main Lua code outside any of the callbacks. That's because the database connections have not been set up yet.
1 parent c8eb37e commit facdb98

2 files changed

Lines changed: 35 additions & 24 deletions

File tree

src/output-flex.cpp

Lines changed: 34 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -735,29 +735,32 @@ bool output_flex_t::relation_cache_t::add_members(middle_query_t const &middle)
735735
return true;
736736
}
737737

738-
osmium::OSMObject const &
738+
osmium::OSMObject const *
739739
output_flex_t::check_and_get_context_object(flex_table_t const &table)
740740
{
741741
if (m_calling_context == calling_context::process_node) {
742742
if (!table.matches_type(osmium::item_type::node)) {
743743
throw fmt_error("Trying to add node to table '{}'.", table.name());
744744
}
745-
return *m_context_node;
745+
return m_context_node;
746746
}
747747

748748
if (m_calling_context == calling_context::process_way) {
749749
if (!table.matches_type(osmium::item_type::way)) {
750750
throw fmt_error("Trying to add way to table '{}'.", table.name());
751751
}
752-
return m_way_cache.get();
752+
return &m_way_cache.get();
753753
}
754754

755-
assert(m_calling_context == calling_context::process_relation);
756-
757-
if (!table.matches_type(osmium::item_type::relation)) {
758-
throw fmt_error("Trying to add relation to table '{}'.", table.name());
755+
if (m_calling_context == calling_context::process_relation) {
756+
if (!table.matches_type(osmium::item_type::relation)) {
757+
throw fmt_error("Trying to add relation to table '{}'.",
758+
table.name());
759+
}
760+
return &m_relation_cache.get();
759761
}
760-
return m_relation_cache.get();
762+
763+
return nullptr;
761764
}
762765

763766
int output_flex_t::table_insert()
@@ -766,34 +769,32 @@ int output_flex_t::table_insert()
766769
return 0;
767770
}
768771

769-
if (m_calling_context != calling_context::process_node &&
770-
m_calling_context != calling_context::process_way &&
771-
m_calling_context != calling_context::process_relation) {
772-
throw std::runtime_error{
773-
"The function insert() can only be called from the "
774-
"process_node/way/relation() functions."};
775-
}
776-
777772
auto const num_params = lua_gettop(lua_state());
778773
if (num_params != 2) {
779774
throw std::runtime_error{
780775
"Need two parameters: The osm2pgsql.Table and the row data."};
781776
}
782777

783778
// The first parameter is the table object.
784-
auto &table_connection = m_table_connections.at(
785-
idx_from_param(lua_state(), OSM2PGSQL_TABLE_CLASS));
779+
std::size_t const idx = idx_from_param(lua_state(), OSM2PGSQL_TABLE_CLASS);
780+
if (idx >= m_table_connections.size()) {
781+
throw std::runtime_error{"Tables not initialized yet. Insert can only "
782+
"be called from processing functions."};
783+
}
784+
auto &table_connection = m_table_connections.at(idx);
786785

787786
// The second parameter must be a Lua table with the contents for the
788787
// fields.
789788
luaL_checktype(lua_state(), 2, LUA_TTABLE);
790789
lua_remove(lua_state(), 1);
791790

792791
auto const &table = table_connection.table();
793-
auto const &object = check_and_get_context_object(table);
794-
osmid_t const id = table.map_id(object.type(), object.id());
792+
auto const *object = check_and_get_context_object(table);
793+
794+
auto const objtype = object ? object->type() : osmium::item_type::undefined;
795+
osmid_t const id = object ? table.map_id(objtype, object->id()) : 0;
795796

796-
if (table.with_id_cache()) {
797+
if (id && table.with_id_cache()) {
797798
get_id_cache(table).push_back(id);
798799
}
799800

@@ -806,8 +807,16 @@ int output_flex_t::table_insert()
806807
continue;
807808
}
808809
if (column.type() == table_column_type::id_type) {
809-
copy_mgr->add_column(type_to_char(object.type()));
810+
if (objtype == osmium::item_type::undefined) {
811+
throw fmt_error("No context object for column '{}'",
812+
column.name());
813+
}
814+
copy_mgr->add_column(type_to_char(objtype));
810815
} else if (column.type() == table_column_type::id_num) {
816+
if (id == 0) {
817+
throw fmt_error("No context object for column '{}'",
818+
column.name());
819+
}
811820
copy_mgr->add_column(id);
812821
} else {
813822
flex_write_column(lua_state(), &m_geometry_cache, copy_mgr,
@@ -820,7 +829,9 @@ int output_flex_t::table_insert()
820829
lua_pushboolean(lua_state(), false);
821830
lua_pushliteral(lua_state(), "null value in not null column.");
822831
luaX_pushstring(lua_state(), e.column().name());
823-
push_osm_object_to_lua_stack(lua_state(), object);
832+
if (object) {
833+
push_osm_object_to_lua_stack(lua_state(), *object);
834+
}
824835
table_connection.increment_not_null_error_counter();
825836
return 4;
826837
}

src/output-flex.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ class output_flex_t : public output_t
202202
void check_context_and_state(char const *name, char const *context,
203203
bool condition);
204204

205-
osmium::OSMObject const &
205+
osmium::OSMObject const *
206206
check_and_get_context_object(flex_table_t const &table);
207207

208208
void node_delete(osmid_t id);

0 commit comments

Comments
 (0)