bool middle_pgsql_t::relations_get(osmid_t id, memberlist_t &members, taglist_t &tags) const { char tmp[16]; char const *paramValues[1]; PGconn *sql_conn = rel_table->sql_conn; taglist_t member_temp; // Make sure we're out of copy mode */ pgsql_endCopy( rel_table ); snprintf(tmp, sizeof(tmp), "%" PRIdOSMID, id); paramValues[0] = tmp; PGresult *res = pgsql_execPrepared(sql_conn, "get_rel", 1, paramValues, PGRES_TUPLES_OK); // Fields are: members, tags, member_count */ if (PQntuples(res) != 1) { PQclear(res); return false; } pgsql_parse_tags(PQgetvalue(res, 0, 1), tags); pgsql_parse_tags(PQgetvalue(res, 0, 0), member_temp); if (member_temp.size() != strtoul(PQgetvalue(res, 0, 2), nullptr, 10)) { fprintf(stderr, "Unexpected member_count reading relation %" PRIdOSMID "\n", id); util::exit_nicely(); } PQclear(res); for (taglist_t::const_iterator it = member_temp.begin(); it != member_temp.end(); ++it) { char tag = it->key[0]; OsmType type = (tag == 'n')?OSMTYPE_NODE:(tag == 'w')?OSMTYPE_WAY:(tag == 'r')?OSMTYPE_RELATION:((OsmType)-1); members.push_back(member(type, strtoosmid(it->key.c_str()+1, nullptr, 10 ), it->value)); } return true; }
int output_multi_t::relation_add(osmid_t id, const memberlist_t &members, const taglist_t &tags) { if (m_processor->interests(geometry_processor::interest_relation) && !members.empty()) { return process_relation(id, members, tags, 0); } 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]); } } }