/* This is the workhorse of pgsql_add_relation, split out because it is used as the callback for iterate relations */ int output_pgsql_t::pgsql_process_relation(osmid_t id, const memberlist_t &members, const taglist_t &tags, int exists, bool pending) { /* If the flag says this object may exist already, delete it first */ if(exists) pgsql_delete_relation_from_output(id); taglist_t outtags; if (m_tagtransform->filter_rel_tags(tags, *m_export_list.get(), outtags)) return 1; idlist_t xid2; multitaglist_t xtags2; multinodelist_t xnodes; for (memberlist_t::const_iterator it = members.begin(); it != members.end(); ++it) { /* Need to handle more than just ways... */ if (it->type == OSMTYPE_WAY) xid2.push_back(it->id); } idlist_t xid; m_mid->ways_get_list(xid2, xid, xtags2, xnodes); int polygon = 0, roads = 0; multitaglist_t xtags(xid.size(), taglist_t()); rolelist_t xrole(xid.size(), 0); for (size_t i = 0; i < xid.size(); i++) { for (size_t j = i; j < members.size(); j++) { if (members[j].id == xid[i]) { //filter the tags on this member because we got it from the middle //and since the middle is no longer tied to the output it no longer //shares any kind of tag transform and therefore all original tags //will come back and need to be filtered by individual outputs before //using these ways m_tagtransform->filter_way_tags(xtags2[i], &polygon, &roads, *m_export_list.get(), xtags[i]); //TODO: if the filter says that this member is now not interesting we //should decrement the count and remove his nodes and tags etc. for //now we'll just keep him with no tags so he will get filtered later xrole[i] = &members[j].role; break; } } } /* At some point we might want to consider storing the retrieved data in the members, rather than as separate arrays */ pgsql_out_relation(id, outtags, xnodes, xtags, xid, xrole, pending); return 0; }
void middle_pgsql_t::relations_set(osmid_t id, const memberlist_t &members, const taglist_t &tags) { taglist_t member_list; char buf[64]; idlist_t all_parts, node_parts, way_parts, rel_parts; all_parts.reserve(members.size()); node_parts.reserve(members.size()); way_parts.reserve(members.size()); rel_parts.reserve(members.size()); for (memberlist_t::const_iterator it = members.begin(); it != members.end(); ++it) { char type = 0; switch (it->type) { case OSMTYPE_NODE: node_parts.push_back(it->id); type = 'n'; break; case OSMTYPE_WAY: way_parts.push_back(it->id); type = 'w'; break; case OSMTYPE_RELATION: rel_parts.push_back(it->id); type = 'r'; break; default: fprintf(stderr, "Internal error: Unknown member type %d\n", it->type); util::exit_nicely(); } sprintf( buf, "%c%" PRIdOSMID, type, it->id ); member_list.push_back(tag_t(buf, it->role)); } all_parts.insert(all_parts.end(), node_parts.begin(), node_parts.end()); all_parts.insert(all_parts.end(), way_parts.begin(), way_parts.end()); all_parts.insert(all_parts.end(), rel_parts.begin(), rel_parts.end()); copy_buffer.reserve(all_parts.size() * 10 + member_list.size() * 24 + tags.size() * 24 + 64); // Params: id, way_off, rel_off, parts, members, tags */ const char *paramValues[6] = { copy_buffer.c_str(), }; bool copy = rel_table->copyMode; char delim = copy ? '\t' : '\0'; copy_buffer = std::to_string(id); copy_buffer+= delim; paramValues[1] = paramValues[0] + copy_buffer.size(); copy_buffer += std::to_string(node_parts.size()); copy_buffer+= delim; paramValues[2] = paramValues[0] + copy_buffer.size(); copy_buffer += std::to_string(node_parts.size() + way_parts.size()); copy_buffer+= delim; paramValues[3] = paramValues[0] + copy_buffer.size(); buffer_store_nodes(all_parts); copy_buffer+= delim; if (member_list.size() == 0) { paramValues[4] = nullptr; copy_buffer += "\\N"; } else { paramValues[4] = paramValues[0] + copy_buffer.size(); buffer_store_tags(member_list, copy); } copy_buffer+= delim; if (tags.size() == 0) { paramValues[5] = nullptr; copy_buffer += "\\N"; } else { paramValues[5] = paramValues[0] + copy_buffer.size(); buffer_store_tags(tags, copy); } if (copy) { copy_buffer+= '\n'; pgsql_CopyData(__FUNCTION__, rel_table->sql_conn, copy_buffer); } else { buffer_correct_params(paramValues, 6); pgsql_execPrepared(rel_table->sql_conn, "insert_rel", 6, (const char * const *)paramValues, PGRES_COMMAND_OK); } }
int output_gazetteer_t::process_relation(osmid_t id, const memberlist_t &members, const taglist_t &tags) { const std::string *type = tags.get("type"); if (!type) { delete_unused_full('R', id); return 0; } int cmp_waterway = type->compare("waterway"); if (*type == "associatedStreet" || !(*type == "boundary" || *type == "multipolygon" || !cmp_waterway)) { delete_unused_full('R', id); return 0; } places.process_tags(tags); if (m_options.append) delete_unused_classes('R', id); /* Are we interested in this item? */ if (!places.has_data()) return 0; /* get the boundary path (ways) */ idlist_t xid2; for (memberlist_t::const_iterator it = members.begin(); it != members.end(); ++it) { /* only interested in ways */ if (it->type == OSMTYPE_WAY) xid2.push_back(it->id); } if (xid2.empty()) { if (m_options.append) delete_unused_full('R', id); return 0; } multitaglist_t xtags; multinodelist_t xnodes; idlist_t xid; m_mid->ways_get_list(xid2, xid, xtags, xnodes); if (cmp_waterway) { geometry_builder::maybe_wkts_t wkts = builder.build_both(xnodes, 1, 1, 1000000, id); for (const auto& wkt: *wkts) { if (boost::starts_with(wkt.geom, "POLYGON") || boost::starts_with(wkt.geom, "MULTIPOLYGON")) { places.copy_out('R', id, wkt.geom, buffer); flush_place_buffer(); } else { /* add_polygon_error('R', id, "boundary", "adminitrative", &names, countrycode, wkt); */ } } } else { /* waterways result in multilinestrings */ geometry_builder::maybe_wkt_t wkt = builder.build_multilines(xnodes, id); if ((wkt->geom).length() > 0) { places.copy_out('R', id, wkt->geom, buffer); flush_place_buffer(); } } return 0; }
void middle_pgsql_t::relations_set(osmid_t id, const memberlist_t &members, const taglist_t &tags) { // Params: id, way_off, rel_off, parts, members, tags */ const char *paramValues[6]; char *buffer; taglist_t member_list; char buf[64]; idlist_t all_parts, node_parts, way_parts, rel_parts; all_parts.reserve(members.size()); node_parts.reserve(members.size()); way_parts.reserve(members.size()); rel_parts.reserve(members.size()); for (memberlist_t::const_iterator it = members.begin(); it != members.end(); ++it) { char type = 0; switch (it->type) { case OSMTYPE_NODE: node_parts.push_back(it->id); type = 'n'; break; case OSMTYPE_WAY: way_parts.push_back(it->id); type = 'w'; break; case OSMTYPE_RELATION: rel_parts.push_back(it->id); type = 'r'; break; default: fprintf(stderr, "Internal error: Unknown member type %d\n", it->type); util::exit_nicely(); } sprintf( buf, "%c%" PRIdOSMID, type, it->id ); member_list.push_back(tag(buf, it->role)); } all_parts.insert(all_parts.end(), node_parts.begin(), node_parts.end()); all_parts.insert(all_parts.end(), way_parts.begin(), way_parts.end()); all_parts.insert(all_parts.end(), rel_parts.begin(), rel_parts.end()); if (rel_table->copyMode) { char *tag_buf = strdup(pgsql_store_tags(tags,1)); const char *member_buf = pgsql_store_tags(member_list,1); char *parts_buf = pgsql_store_nodes(all_parts); int length = strlen(member_buf) + strlen(tag_buf) + strlen(parts_buf) + 64; buffer = (char *)alloca(length); if (snprintf( buffer, length, "%" PRIdOSMID "\t%zu\t%zu\t%s\t%s\t%s\n", id, node_parts.size(), node_parts.size() + way_parts.size(), parts_buf, member_buf, tag_buf ) > (length-10)) { throw std::runtime_error((boost::format("Buffer overflow relation id %1%") % id).str()); } free(tag_buf); pgsql_CopyData(__FUNCTION__, rel_table->sql_conn, buffer); } else { buffer = (char *)alloca(64); char *ptr = buffer; paramValues[0] = ptr; ptr += sprintf(ptr, "%" PRIdOSMID, id ) + 1; paramValues[1] = ptr; ptr += sprintf(ptr, "%zu", node_parts.size() ) + 1; paramValues[2] = ptr; sprintf( ptr, "%zu", node_parts.size() + way_parts.size() ); paramValues[3] = pgsql_store_nodes(all_parts); paramValues[4] = pgsql_store_tags(member_list,0); if (paramValues[4]) { paramValues[4] = strdup(paramValues[4]); } paramValues[5] = pgsql_store_tags(tags,0); pgsql_execPrepared(rel_table->sql_conn, "insert_rel", 6, (const char * const *)paramValues, PGRES_COMMAND_OK); if (paramValues[4]) { free((void *)paramValues[4]); } } }