void 
writeable_pgsql_selection::write_relations(output_formatter &formatter) {
  logger::message("Fetching relations");
  element_info elem;
  members_t members;
  tags_t tags;

  formatter.start_element_type(element_type_relation);
  pqxx::result relations = w.prepared("extract_relations").exec();
  for (pqxx::result::const_iterator itr = relations.begin(); 
       itr != relations.end(); ++itr) {
    extract_elem(*itr, elem, cc);
    extract_members(w.prepared("extract_relation_members")(elem.id).exec(), members);
    extract_tags(w.prepared("extract_relation_tags")(elem.id).exec(), tags);
    formatter.write_relation(elem, members, tags);
  }
  formatter.end_element_type(element_type_relation);
}
void 
readonly_pgsql_selection::write_ways(output_formatter &formatter) {
  // grab the ways, way nodes and tags
  // way nodes and tags are on a separate connections so that the
  // entire result set can be streamed from a single query.
  logger::message("Fetching ways");
  element_info elem;
  nodes_t nodes;
  tags_t tags;
  
  formatter.start_element_type(element_type_way);
  // fetch in chunks...
  set<osm_id_t>::iterator prev_itr = sel_ways.begin();
  size_t chunk_i = 0;
  for (set<osm_id_t>::iterator n_itr = sel_ways.begin();
       ; ++n_itr, ++chunk_i) {
    bool at_end = n_itr == sel_ways.end();
    if ((chunk_i >= STRIDE) || ((chunk_i > 0) && at_end)) {
      stringstream query;
      query << "select w.id, w.visible, w.version, w.changeset_id, "
        "to_char(w.timestamp,'YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as timestamp from "
        "current_ways w where w.id in (";
      std::copy(prev_itr, n_itr, infix_ostream_iterator<osm_id_t>(query, ","));
      query << ")";
      pqxx::result ways = w.exec(query);
      
      for (pqxx::result::const_iterator itr = ways.begin(); 
           itr != ways.end(); ++itr) {
        extract_elem(*itr, elem, cc);
        extract_nodes(w.prepared("extract_way_nds")(elem.id).exec(), nodes);
        extract_tags(w.prepared("extract_way_tags")(elem.id).exec(), tags);
        formatter.write_way(elem, nodes, tags);
      }
      
      chunk_i = 0;
      prev_itr = n_itr;
    }
    
    if (at_end) break;
  }
  formatter.end_element_type(element_type_way);
}
void 
readonly_pgsql_selection::write_nodes(output_formatter &formatter) {
  // get all nodes - they already contain their own tags, so
  // we don't need to do anything else.
  logger::message("Fetching nodes");
  element_info elem;
  double lon, lat;
  tags_t tags;
  
  formatter.start_element_type(element_type_node);
  // fetch in chunks...
  set<osm_id_t>::iterator prev_itr = sel_nodes.begin();
  size_t chunk_i = 0;
  for (set<osm_id_t>::iterator n_itr = sel_nodes.begin();
       ; ++n_itr, ++chunk_i) {
    bool at_end = n_itr == sel_nodes.end();
    if ((chunk_i >= STRIDE) || ((chunk_i > 0) && at_end)) {
      stringstream query;
      query << "select n.id, n.latitude, n.longitude, n.visible, "
        "to_char(n.timestamp,'YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as timestamp, "
        "n.changeset_id, n.version from current_nodes n where n.id in (";
      std::copy(prev_itr, n_itr, infix_ostream_iterator<osm_id_t>(query, ","));
      query << ")";
      pqxx::result nodes = w.exec(query);
      
      for (pqxx::result::const_iterator itr = nodes.begin(); 
           itr != nodes.end(); ++itr) {
        extract_elem(*itr, elem, cc);
        lon = double((*itr)["longitude"].as<int64_t>()) / (SCALE);
        lat = double((*itr)["latitude"].as<int64_t>()) / (SCALE);
        extract_tags(w.prepared("extract_node_tags")(elem.id).exec(), tags);
        formatter.write_node(elem, lon, lat, tags);
      }
      
      chunk_i = 0;
      prev_itr = n_itr;
    }
    
    if (at_end) break;
  }
  formatter.end_element_type(element_type_node);
}
void 
writeable_pgsql_selection::write_ways(output_formatter &formatter) {
  // grab the ways, way nodes and tags
  // way nodes and tags are on a separate connections so that the
  // entire result set can be streamed from a single query.
  logger::message("Fetching ways");
  element_info elem;
  nodes_t nodes;
  tags_t tags;

  formatter.start_element_type(element_type_way);
  pqxx::result ways = w.prepared("extract_ways").exec();
  for (pqxx::result::const_iterator itr = ways.begin(); 
       itr != ways.end(); ++itr) {
    extract_elem(*itr, elem, cc);
    extract_nodes(w.prepared("extract_way_nds")(elem.id).exec(), nodes);
    extract_tags(w.prepared("extract_way_tags")(elem.id).exec(), tags);
    formatter.write_way(elem, nodes, tags);
  }
  formatter.end_element_type(element_type_way);
}
void 
writeable_pgsql_selection::write_nodes(output_formatter &formatter) {
  // get all nodes - they already contain their own tags, so
  // we don't need to do anything else.
  logger::message("Fetching nodes");
  element_info elem;
  double lon, lat;
  tags_t tags;

  formatter.start_element_type(element_type_node);
  pqxx::result nodes = w.prepared("extract_nodes").exec();
  for (pqxx::result::const_iterator itr = nodes.begin(); 
       itr != nodes.end(); ++itr) {
    extract_elem(*itr, elem, cc);
    lon = double((*itr)["longitude"].as<int64_t>()) / (SCALE);
    lat = double((*itr)["latitude"].as<int64_t>()) / (SCALE);
    extract_tags(w.prepared("extract_node_tags")(elem.id).exec(), tags);
    formatter.write_node(elem, lon, lat, tags);
  }
  formatter.end_element_type(element_type_node);
}
void 
readonly_pgsql_selection::write_relations(output_formatter &formatter) {
  logger::message("Fetching relations");
  element_info elem;
  members_t members;
  tags_t tags;
  
  formatter.start_element_type(element_type_relation);
  // fetch in chunks...
  set<osm_id_t>::iterator prev_itr = sel_relations.begin();
  size_t chunk_i = 0;
  for (set<osm_id_t>::iterator n_itr = sel_relations.begin();
       ; ++n_itr, ++chunk_i) {
    bool at_end = n_itr == sel_relations.end();
    if ((chunk_i >= STRIDE) || ((chunk_i > 0) && at_end)) {
      stringstream query;
      query << "select r.id, r.visible, r.version, r.changeset_id, "
        "to_char(r.timestamp,'YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as timestamp from "
        "current_relations r where r.id in (";
      std::copy(prev_itr, n_itr, infix_ostream_iterator<osm_id_t>(query, ","));
      query << ")";
      pqxx::result relations = w.exec(query);
      
      for (pqxx::result::const_iterator itr = relations.begin(); 
           itr != relations.end(); ++itr) {
        extract_elem(*itr, elem, cc);
        extract_members(w.prepared("extract_relation_members")(elem.id).exec(), members);
        extract_tags(w.prepared("extract_relation_tags")(elem.id).exec(), tags);
        formatter.write_relation(elem, members, tags);
      }
      
      chunk_i = 0;
      prev_itr = n_itr;
    }
    
    if (at_end) break;
  }
  formatter.end_element_type(element_type_relation);
}
void snapshot_selection::write_nodes(output_formatter &formatter) {
  // get all nodes - they already contain their own tags, so
  // we don't need to do anything else.
  logger::message("Fetching nodes");
  element_info elem;
  tags_t tags;

  pqxx::result nodes = w.prepared("extract_nodes").exec();
  for (pqxx::result::const_iterator itr = nodes.begin(); itr != nodes.end();
       ++itr) {
    extract_elem(*itr, elem);
    if (itr["untagged"].as<bool>()) {
      tags.clear();
    } else {
      extract_tags(w.prepared("extract_node_tags")(elem.id).exec(), tags);
    }
    formatter.write_node(elem, (*itr)["lon"].as<double>(),
                         (*itr)["lat"].as<double>(), tags);
  }
}