Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add completeRelations option to pgsnapshot dataset bounding box filter #36

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,12 @@ public interface DatasetContext extends Completable {
* @param completeWays
* If true, all nodes within the ways will be returned even if
* they lie outside the box.
* @param completeRelations
* If true, all ways within the relations will be returned even if
* they lie outside the box.
* @return An iterator pointing to the start of the result data.
*/
ReleasableIterator<EntityContainer> iterateBoundingBox(
double left, double right, double top, double bottom, boolean completeWays);
double left, double right, double top, double bottom, boolean completeWays,
boolean completeRelations);
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ public class DatasetBoundingBoxFilter implements DatasetSinkSource {
private double top;
private double bottom;
private boolean completeWays;
private boolean completeRelations;
private DatasetContext datasetReader;


Expand All @@ -44,13 +45,18 @@ public class DatasetBoundingBoxFilter implements DatasetSinkSource {
* @param completeWays
* Include all nodes for ways which have some portion inside the
* filtered area.
* @param completeRelations
* Include all ways for relations which have some portion inside the
* filtered area.
*/
public DatasetBoundingBoxFilter(double left, double right, double top, double bottom, boolean completeWays) {
public DatasetBoundingBoxFilter(double left, double right, double top, double bottom, boolean completeWays,
boolean completeRelations) {
this.left = left;
this.right = right;
this.top = top;
this.bottom = bottom;
this.completeWays = completeWays;
this.completeRelations = completeRelations;
}


Expand All @@ -76,7 +82,8 @@ public void process(Dataset dataset) {

// Pass all data within the bounding box to the sink.
try (ReleasableIterator<EntityContainer> bboxData =
datasetReader.iterateBoundingBox(left, right, top, bottom, completeWays)) {
datasetReader.iterateBoundingBox(left, right, top, bottom, completeWays,
completeRelations)) {

sink.initialize(Collections.<String, Object>emptyMap());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ public class DatasetBoundingBoxFilterFactory extends TaskManagerFactory {
private static final double DEFAULT_TOP = 90;
private static final double DEFAULT_BOTTOM = -90;
private static final String ARG_COMPLETE_WAYS = "completeWays";
private static final String ARG_COMPLETE_RELATIONS = "completeRelations";
private static final boolean DEFAULT_COMPLETE_WAYS = false;
private static final boolean DEFAULT_COMPLETE_RELATIONS = false;


/**
Expand All @@ -35,17 +37,19 @@ protected TaskManager createTaskManagerImpl(TaskConfiguration taskConfig) {
double top;
double bottom;
boolean completeWays;
boolean completeRelations;

// Get the task arguments.
left = getDoubleArgument(taskConfig, ARG_LEFT, DEFAULT_LEFT);
right = getDoubleArgument(taskConfig, ARG_RIGHT, DEFAULT_RIGHT);
top = getDoubleArgument(taskConfig, ARG_TOP, DEFAULT_TOP);
bottom = getDoubleArgument(taskConfig, ARG_BOTTOM, DEFAULT_BOTTOM);
completeWays = getBooleanArgument(taskConfig, ARG_COMPLETE_WAYS, DEFAULT_COMPLETE_WAYS);
completeRelations = getBooleanArgument(taskConfig, ARG_COMPLETE_RELATIONS, DEFAULT_COMPLETE_RELATIONS);

return new DatasetSinkSourceManager(
taskConfig.getId(),
new DatasetBoundingBoxFilter(left, right, top, bottom, completeWays),
new DatasetBoundingBoxFilter(left, right, top, bottom, completeWays, completeRelations),
taskConfig.getPipeArgs()
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,8 @@ private ReleasableIterator<Long> getRelationIdsOwningWay(long wayId) {
*/
private ReleasableIterator<Long> getRelationIdsOwningRelation(long relationId) {
return new RelationalIndexValueIdIterator(
relationStorageContainer.getRelationRelationIndexReader().getRange(relationId, relationId));
relationStorageContainer.getRelationRelationIndexReader().getRange(relationId,
relationId));
}


Expand Down Expand Up @@ -343,8 +344,9 @@ private void populateWayIdsUsingTileWayIndex(BoundingBoxContext bboxCtx, boolean
// Ignore any referential integrity problems.
if (LOG.isLoggable(Level.FINER)) {
LOG.finest(
"Ignoring referential integrity problem where way " + wayId
+ " refers to non-existent node " + wayNode.getNodeId() + "."
"Ignoring referential integrity problem where way "
+ wayId + " refers to non-existent node "
+ wayNode.getNodeId() + "."
);
}
}
Expand Down Expand Up @@ -449,7 +451,8 @@ private void populateRelationIds(BoundingBoxContext bboxCtx) {
moreParents = false;

for (Long relationId : bboxCtx.relationIdTracker) {
try (ReleasableIterator<Long> relationIdIterator = getRelationIdsOwningRelation(relationId)) {
try (ReleasableIterator<Long> relationIdIterator
= getRelationIdsOwningRelation(relationId)) {
while (relationIdIterator.hasNext()) {
long parentRelationId;

Expand All @@ -472,7 +475,8 @@ private void populateRelationIds(BoundingBoxContext bboxCtx) {
*/
@Override
public ReleasableIterator<EntityContainer> iterateBoundingBox(
double left, double right, double top, double bottom, boolean completeWays) {
double left, double right, double top, double bottom, boolean completeWays,
boolean completeRelations) {
BoundingBoxContext bboxCtx;

LOG.fine("Beginning bounding box iteration.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,8 @@ public ReleasableIterator<EntityContainer> iterate() {
sources = new ArrayList<ReleasableIterator<EntityContainer>>();

sources.add(new UpcastIterator<EntityContainer, BoundContainer>(
new BoundContainerIterator(new ReleasableAdaptorForIterator<Bound>(bounds.iterator()))));
new BoundContainerIterator(
new ReleasableAdaptorForIterator<Bound>(bounds.iterator()))));
sources.add(new UpcastIterator<EntityContainer, NodeContainer>(
new NodeContainerIterator(nodeDao.iterate())));
sources.add(new UpcastIterator<EntityContainer, WayContainer>(
Expand All @@ -226,7 +227,8 @@ public ReleasableIterator<EntityContainer> iterate() {
*/
@Override
public ReleasableIterator<EntityContainer> iterateBoundingBox(
double left, double right, double top, double bottom, boolean completeWays) {
double left, double right, double top, double bottom, boolean completeWays,
boolean completeRelations) {
List<Bound> bounds;
PreparedStatement preparedStatement = null;
int prmIndex;
Expand Down Expand Up @@ -255,13 +257,16 @@ public ReleasableIterator<EntityContainer> iterateBoundingBox(

// Create a temporary table capable of holding node ids.
LOG.finer("Creating node id temp table.");
dbCtx.executeStatement("CREATE TEMPORARY TABLE box_node_list (id bigint PRIMARY KEY) ON COMMIT DROP");
dbCtx.executeStatement(
"CREATE TEMPORARY TABLE box_node_list (id bigint PRIMARY KEY) ON COMMIT DROP");
// Create a temporary table capable of holding way ids.
LOG.finer("Creating way id temp table.");
dbCtx.executeStatement("CREATE TEMPORARY TABLE box_way_list (id bigint PRIMARY KEY) ON COMMIT DROP");
dbCtx.executeStatement(
"CREATE TEMPORARY TABLE box_way_list (id bigint PRIMARY KEY) ON COMMIT DROP");
// Create a temporary table capable of holding relation ids.
LOG.finer("Creating relation id temp table.");
dbCtx.executeStatement("CREATE TEMPORARY TABLE box_relation_list (id bigint PRIMARY KEY) ON COMMIT DROP");
dbCtx.executeStatement(
"CREATE TEMPORARY TABLE box_relation_list (id bigint PRIMARY KEY) ON COMMIT DROP");

// Build a polygon representing the bounding box.
// Sample box for query testing may be:
Expand Down Expand Up @@ -338,7 +343,8 @@ public ReleasableIterator<EntityContainer> iterateBoundingBox(
// the selected nodes.
preparedStatement = dbCtx.prepareStatement(
"INSERT INTO box_way_list "
+ "SELECT wn.way_id FROM way_nodes wn INNER JOIN box_node_list n ON wn.node_id = n.id"
+ "SELECT wn.way_id FROM way_nodes wn INNER JOIN box_node_list n"
+ " ON wn.node_id = n.id"
+ " GROUP BY wn.way_id"
);
}
Expand All @@ -352,8 +358,8 @@ public ReleasableIterator<EntityContainer> iterateBoundingBox(
preparedStatement = dbCtx.prepareStatement(
"INSERT INTO box_relation_list ("
+ "SELECT rm.relation_id AS relation_id FROM relation_members rm"
+ " INNER JOIN box_node_list n ON rm.member_id = n.id WHERE rm.member_type = ? "
+ "UNION "
+ " INNER JOIN box_node_list n ON rm.member_id = n.id WHERE rm.member_type = ?"
+ " UNION "
+ "SELECT rm.relation_id AS relation_id FROM relation_members rm"
+ " INNER JOIN box_way_list w ON rm.member_id = w.id WHERE rm.member_type = ?"
+ ")"
Expand All @@ -373,12 +379,14 @@ public ReleasableIterator<EntityContainer> iterateBoundingBox(
preparedStatement = dbCtx.prepareStatement(
"INSERT INTO box_relation_list "
+ "SELECT rm.relation_id AS relation_id FROM relation_members rm"
+ " INNER JOIN box_relation_list r ON rm.member_id = r.id WHERE rm.member_type = ? "
+ " INNER JOIN box_relation_list r ON rm.member_id = r.id "
+ "WHERE rm.member_type = ? "
+ "EXCEPT "
+ "SELECT id AS relation_id FROM box_relation_list"
);
prmIndex = 1;
preparedStatement.setString(prmIndex++, memberTypeValueMapper.getMemberType(EntityType.Relation));
preparedStatement.setString(prmIndex++,
memberTypeValueMapper.getMemberType(EntityType.Relation));
rowCount = preparedStatement.executeUpdate();
preparedStatement.close();
preparedStatement = null;
Expand All @@ -390,7 +398,8 @@ public ReleasableIterator<EntityContainer> iterateBoundingBox(
LOG.finer("Selecting all node ids for selected ways.");
preparedStatement = dbCtx.prepareStatement(
"INSERT INTO box_node_list "
+ "SELECT wn.node_id AS id FROM way_nodes wn INNER JOIN box_way_list bw ON wn.way_id = bw.id "
+ "SELECT wn.node_id AS id FROM way_nodes wn INNER JOIN box_way_list bw"
+ " ON wn.way_id = bw.id "
+ "EXCEPT "
+ "SELECT id AS node_id FROM box_node_list"
);
Expand All @@ -411,16 +420,18 @@ public ReleasableIterator<EntityContainer> iterateBoundingBox(
resultSets = new ArrayList<ReleasableIterator<EntityContainer>>();
resultSets.add(
new UpcastIterator<EntityContainer, BoundContainer>(
new BoundContainerIterator(new ReleasableAdaptorForIterator<Bound>(bounds.iterator()))));
new BoundContainerIterator(
new ReleasableAdaptorForIterator<Bound>(bounds.iterator()))));
resultSets.add(
new UpcastIterator<EntityContainer, NodeContainer>(
new NodeContainerIterator(new NodeReader(dbCtx, "box_node_list"))));
new NodeContainerIterator(new NodeReader(dbCtx, "box_node_list"))));
resultSets.add(
new UpcastIterator<EntityContainer, WayContainer>(
new WayContainerIterator(new WayReader(dbCtx, "box_way_list"))));
new WayContainerIterator(new WayReader(dbCtx, "box_way_list"))));
resultSets.add(
new UpcastIterator<EntityContainer, RelationContainer>(
new RelationContainerIterator(new RelationReader(dbCtx, "box_relation_list"))));
new RelationContainerIterator(
new RelationReader(dbCtx, "box_relation_list"))));

// Merge all readers into a single result iterator and return.
return new MultipleSourceIterator<EntityContainer>(resultSets);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,8 @@ public ReleasableIterator<EntityContainer> iterate() {
sources = new ArrayList<ReleasableIterator<EntityContainer>>();

sources.add(new UpcastIterator<EntityContainer, BoundContainer>(
new BoundContainerIterator(new ReleasableAdaptorForIterator<Bound>(bounds.iterator()))));
new BoundContainerIterator(
new ReleasableAdaptorForIterator<Bound>(bounds.iterator()))));
sources.add(new UpcastIterator<EntityContainer, NodeContainer>(
new NodeContainerIterator(nodeDao.iterate())));
sources.add(new UpcastIterator<EntityContainer, WayContainer>(
Expand All @@ -221,7 +222,8 @@ public ReleasableIterator<EntityContainer> iterate() {
*/
@Override
public ReleasableIterator<EntityContainer> iterateBoundingBox(
double left, double right, double top, double bottom, boolean completeWays) {
double left, double right, double top, double bottom, boolean completeWays,
boolean completeRelations) {
List<Bound> bounds;
Point[] bboxPoints;
Polygon bboxPolygon;
Expand Down Expand Up @@ -295,8 +297,9 @@ public ReleasableIterator<EntityContainer> iterateBoundingBox(
rowCount = jdbcTemplate.update(
"CREATE TEMPORARY TABLE bbox_ways ON COMMIT DROP AS"
+ " SELECT w.* FROM ("
+ "SELECT c.id AS id, First(c.version) AS version, First(c.user_id) AS user_id,"
+ " First(c.tstamp) AS tstamp, First(c.changeset_id) AS changeset_id, First(c.tags) AS tags,"
+ "SELECT c.id AS id, First(c.version) AS version, First(c.user_id)"
+ " AS user_id, First(c.tstamp) AS tstamp, First(c.changeset_id)"
+ " AS changeset_id, First(c.tags) AS tags,"
+ " First(c.nodes) AS nodes, ST_MakeLine(c.geom) AS way_line FROM ("
+ "SELECT w.*, n.geom AS geom FROM nodes n"
+ " INNER JOIN way_nodes wn ON n.id = wn.node_id"
Expand Down Expand Up @@ -349,7 +352,8 @@ public ReleasableIterator<EntityContainer> iterateBoundingBox(
LOG.finer(rowCount + " rows affected.");

LOG.finer("Adding a primary key to the temporary relations table.");
jdbcTemplate.update("ALTER TABLE ONLY bbox_relations ADD CONSTRAINT pk_bbox_relations PRIMARY KEY (id)");
jdbcTemplate.update("ALTER TABLE ONLY bbox_relations ADD CONSTRAINT"
+ "pk_bbox_relations PRIMARY KEY (id)");

LOG.finer("Updating query analyzer statistics on the temporary relations table.");
jdbcTemplate.update("ANALYZE bbox_relations");
Expand All @@ -374,6 +378,35 @@ public ReleasableIterator<EntityContainer> iterateBoundingBox(
LOG.finer("Updating query analyzer statistics on the temporary relations table.");
jdbcTemplate.update("ANALYZE bbox_relations");

// If complete relations is set, select all ways contained by the relations into the ways temp table.
if (completeRelations) {
LOG.finer("Selecting all ways for selected relations.");
jdbcTemplate.update(
"CREATE TEMPORARY TABLE bbox_relation_ways ON COMMIT DROP AS"
+ " SELECT way_id AS id FROM ("
+ " SELECT rm.member_id AS way_id FROM relation_members rm"
+ " INNER JOIN bbox_relations br ON rm.relation_id = br.id"
+ " WHERE rm.member_type = 'W'"
+ " ) wids GROUP BY way_id"
);
jdbcTemplate.update(
"CREATE TEMPORARY TABLE bbox_missing_ways ON COMMIT DROP AS "
+ "SELECT buw.id FROM (SELECT DISTINCT brw.id FROM bbox_relation_ways brw) buw"
+ " WHERE NOT EXISTS ("
+ " SELECT * FROM bbox_ways WHERE id = buw.id"
+ ");"
);
jdbcTemplate.update("ALTER TABLE ONLY bbox_missing_ways"
+ " ADD CONSTRAINT pk_bbox_missing_ways PRIMARY KEY (id)");
jdbcTemplate.update("ANALYZE bbox_missing_ways");
rowCount = jdbcTemplate.update("INSERT INTO bbox_ways "
+ "SELECT w.* FROM ways w INNER JOIN bbox_missing_ways bw ON w.id = bw.id;");
LOG.finer(rowCount + " rows affected.");

LOG.finer("Updating query analyzer statistics on the temporary ways table.");
jdbcTemplate.update("ANALYZE bbox_ways");
}

// If complete ways is set, select all nodes contained by the ways into the node temp table.
if (completeWays) {
LOG.finer("Selecting all nodes for selected ways.");
Expand All @@ -389,8 +422,8 @@ public ReleasableIterator<EntityContainer> iterateBoundingBox(
jdbcTemplate.update("ALTER TABLE ONLY bbox_missing_way_nodes"
+ " ADD CONSTRAINT pk_bbox_missing_way_nodes PRIMARY KEY (id)");
jdbcTemplate.update("ANALYZE bbox_missing_way_nodes");
rowCount = jdbcTemplate.update("INSERT INTO bbox_nodes "
+ "SELECT n.* FROM nodes n INNER JOIN bbox_missing_way_nodes bwn ON n.id = bwn.id;");
rowCount = jdbcTemplate.update("INSERT INTO bbox_nodes SELECT"
+ " n.* FROM nodes n INNER JOIN bbox_missing_way_nodes bwn ON n.id = bwn.id;");
LOG.finer(rowCount + " rows affected.");
}

Expand All @@ -402,7 +435,8 @@ public ReleasableIterator<EntityContainer> iterateBoundingBox(
resultSets = new ArrayList<ReleasableIterator<EntityContainer>>();
resultSets.add(
new UpcastIterator<EntityContainer, BoundContainer>(
new BoundContainerIterator(new ReleasableAdaptorForIterator<Bound>(bounds.iterator()))));
new BoundContainerIterator(
new ReleasableAdaptorForIterator<Bound>(bounds.iterator()))));
resultSets.add(
new UpcastIterator<EntityContainer, NodeContainer>(
new NodeContainerIterator(nodeDao.iterate("bbox_"))));
Expand Down