-
Notifications
You must be signed in to change notification settings - Fork 192
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
Make spatial query procedures read only #403
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,6 +20,7 @@ | |
package org.neo4j.gis.spatial.procedures; | ||
|
||
import static org.neo4j.gis.spatial.SpatialDatabaseService.RTREE_INDEX_NAME; | ||
import static org.neo4j.procedure.Mode.READ; | ||
import static org.neo4j.procedure.Mode.WRITE; | ||
|
||
import java.io.File; | ||
|
@@ -182,7 +183,7 @@ public Stream<NameResult> upgradeSpatial() { | |
return builder.build(); | ||
} | ||
|
||
@Procedure(value = "spatial.layers", mode = WRITE) | ||
@Procedure(value = "spatial.layers", mode = READ) | ||
@Description("Returns name, and details for all layers") | ||
public Stream<NameResult> getAllLayers() { | ||
SpatialDatabaseService sdb = spatial(); | ||
|
@@ -521,21 +522,27 @@ public void removeLayer(@Name("name") String name) { | |
@Description("Adds the given node to the layer, returns the geometry-node") | ||
public Stream<NodeResult> addNodeToLayer(@Name("layerName") String name, @Name("node") Node node) { | ||
EditableLayer layer = getEditableLayerOrThrow(tx, spatial(), name); | ||
return streamNode(layer.add(tx, node).getGeomNode()); | ||
Node geomNode = layer.add(tx, node).getGeomNode(); | ||
layer.close(tx); | ||
return streamNode(geomNode); | ||
} | ||
|
||
@Procedure(value = "spatial.addNodes", mode = WRITE) | ||
@Description("Adds the given nodes list to the layer, returns the count") | ||
public Stream<CountResult> addNodesToLayer(@Name("layerName") String name, @Name("nodes") List<Node> nodes) { | ||
EditableLayer layer = getEditableLayerOrThrow(tx, spatial(), name); | ||
return Stream.of(new CountResult(layer.addAll(tx, nodes))); | ||
int count = layer.addAll(tx, nodes); | ||
layer.close(tx); | ||
return Stream.of(new CountResult(count)); | ||
} | ||
|
||
@Procedure(value = "spatial.addNode.byId", mode = WRITE) | ||
@Description("Adds the given node to the layer, returns the geometry-node") | ||
public Stream<NodeResult> addNodeIdToLayer(@Name("layerName") String name, @Name("nodeId") String nodeId) { | ||
EditableLayer layer = getEditableLayerOrThrow(tx, spatial(), name); | ||
return streamNode(layer.add(tx, tx.getNodeByElementId(nodeId)).getGeomNode()); | ||
Node geomNode = layer.add(tx, tx.getNodeByElementId(nodeId)).getGeomNode(); | ||
layer.close(tx); | ||
return streamNode(geomNode); | ||
} | ||
|
||
@Procedure(value = "spatial.addNodes.byId", mode = WRITE) | ||
|
@@ -544,14 +551,17 @@ public Stream<CountResult> addNodeIdsToLayer(@Name("layerName") String name, | |
@Name("nodeIds") List<String> nodeIds) { | ||
EditableLayer layer = getEditableLayerOrThrow(tx, spatial(), name); | ||
List<Node> nodes = nodeIds.stream().map(id -> tx.getNodeByElementId(id)).collect(Collectors.toList()); | ||
return Stream.of(new CountResult(layer.addAll(tx, nodes))); | ||
int count = layer.addAll(tx, nodes); | ||
layer.close(tx); | ||
return Stream.of(new CountResult(count)); | ||
} | ||
|
||
@Procedure(value = "spatial.removeNode", mode = WRITE) | ||
@Description("Removes the given node from the layer, returns the geometry-node") | ||
public Stream<NodeIdResult> removeNodeFromLayer(@Name("layerName") String name, @Name("node") Node node) { | ||
EditableLayer layer = getEditableLayerOrThrow(tx, spatial(), name); | ||
layer.removeFromIndex(tx, node.getElementId()); | ||
layer.close(tx); | ||
return streamNode(node.getElementId()); | ||
} | ||
|
||
|
@@ -565,6 +575,7 @@ public Stream<CountResult> removeNodesFromLayer(@Name("layerName") String name, | |
layer.removeFromIndex(tx, node.getElementId()); | ||
} | ||
int after = layer.getIndex().count(tx); | ||
layer.close(tx); | ||
return Stream.of(new CountResult(before - after)); | ||
} | ||
|
||
|
@@ -573,6 +584,7 @@ public Stream<CountResult> removeNodesFromLayer(@Name("layerName") String name, | |
public Stream<NodeIdResult> removeNodeFromLayer(@Name("layerName") String name, @Name("nodeId") String nodeId) { | ||
EditableLayer layer = getEditableLayerOrThrow(tx, spatial(), name); | ||
layer.removeFromIndex(tx, nodeId); | ||
layer.close(tx); | ||
return streamNode(nodeId); | ||
} | ||
|
||
|
@@ -587,6 +599,7 @@ public Stream<CountResult> removeNodeIdsFromLayer(@Name("layerName") String name | |
layer.removeFromIndex(tx, nodeId); | ||
} | ||
int after = layer.getIndex().count(tx); | ||
layer.close(tx); | ||
return Stream.of(new CountResult(before - after)); | ||
} | ||
|
||
|
@@ -596,7 +609,9 @@ public Stream<NodeResult> addGeometryWKTToLayer(@Name("layerName") String name, | |
@Name("geometry") String geometryWKT) { | ||
EditableLayer layer = getEditableLayerOrThrow(tx, spatial(), name); | ||
WKTReader reader = new WKTReader(layer.getGeometryFactory()); | ||
return streamNode(addGeometryWkt(layer, reader, geometryWKT)); | ||
Node node = addGeometryWkt(layer, reader, geometryWKT); | ||
layer.close(tx); | ||
return streamNode(node); | ||
} | ||
|
||
@Procedure(value = "spatial.addWKTs", mode = WRITE) | ||
|
@@ -606,7 +621,8 @@ public Stream<NodeResult> addGeometryWKTsToLayer(@Name("layerName") String name, | |
EditableLayer layer = getEditableLayerOrThrow(tx, spatial(), name); | ||
WKTReader reader = new WKTReader(layer.getGeometryFactory()); | ||
return geometryWKTs.stream().map(geometryWKT -> addGeometryWkt(layer, reader, geometryWKT)) | ||
.map(NodeResult::new); | ||
.map(NodeResult::new) | ||
.onClose(() -> layer.close(tx)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice trick. Perhaps we could add a lambda for this to the streamNode() method? |
||
} | ||
|
||
private Node addGeometryWkt(EditableLayer layer, WKTReader reader, String geometryWKT) { | ||
|
@@ -624,7 +640,9 @@ public Stream<CountResult> importShapefile( | |
@Name("layerName") String name, | ||
@Name("uri") String uri) throws IOException { | ||
EditableLayerImpl layer = getEditableLayerOrThrow(tx, spatial(), name); | ||
return Stream.of(new CountResult(importShapefileToLayer(uri, layer, 1000).size())); | ||
List<Node> nodes = importShapefileToLayer(uri, layer, 1000); | ||
layer.close(tx); | ||
return Stream.of(new CountResult(nodes.size())); | ||
} | ||
|
||
@Procedure(value = "spatial.importShapefile", mode = WRITE) | ||
|
@@ -744,7 +762,7 @@ public void run() { | |
} | ||
} | ||
|
||
@Procedure(value = "spatial.bbox", mode = WRITE) | ||
@Procedure(value = "spatial.bbox", mode = READ) | ||
@Description("Finds all geometry nodes in the given layer within the lower left and upper right coordinates of a box") | ||
public Stream<NodeResult> findGeometriesInBBox( | ||
@Name("layerName") String name, | ||
|
@@ -758,7 +776,7 @@ public Stream<NodeResult> findGeometriesInBBox( | |
.stream().map(GeoPipeFlow::getGeomNode).map(NodeResult::new); | ||
} | ||
|
||
@Procedure(value = "spatial.closest", mode = WRITE) | ||
@Procedure(value = "spatial.closest", mode = READ) | ||
@Description("Finds all geometry nodes in the layer within the distance to the given coordinate") | ||
public Stream<NodeResult> findClosestGeometries( | ||
@Name("layerName") String name, | ||
|
@@ -772,7 +790,7 @@ public Stream<NodeResult> findClosestGeometries( | |
return edgeResults.stream().map(e -> e.getValue().getGeomNode()).map(NodeResult::new); | ||
} | ||
|
||
@Procedure(value = "spatial.withinDistance", mode = WRITE) | ||
@Procedure(value = "spatial.withinDistance", mode = READ) | ||
@Description("Returns all geometry nodes and their ordered distance in the layer within the distance to the given coordinate") | ||
public Stream<NodeDistanceResult> findGeometriesWithinDistance( | ||
@Name("layerName") String name, | ||
|
@@ -809,7 +827,7 @@ public Stream<GeometryResult> asExternalGeometry( | |
return Stream.of(geometry).map(geom -> new GeometryResult(toNeo4jGeometry(null, geom))); | ||
} | ||
|
||
@Procedure(value = "spatial.intersects", mode = WRITE) | ||
@Procedure(value = "spatial.intersects", mode = READ) | ||
@Description("Returns all geometry nodes that intersect the given geometry (shape, polygon) in the layer") | ||
public Stream<NodeResult> findGeometriesIntersecting( | ||
@Name("layerName") String name, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1544,4 +1544,9 @@ public int compare(NodeWithEnvelope o1, NodeWithEnvelope o2) { | |
return Double.compare(o1.envelope.getArea(), o2.envelope.getArea()); | ||
} | ||
} | ||
|
||
@Override | ||
public void close(Transaction tx) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As mentioned above, I wonder if there is a better choice of word than |
||
saveCount(tx); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The use of the word
close
and in particularclose(tx)
almost makes it feel like the transaction is being closed. It also makes me look for a matchingopen(tx)
statement. I wonder if it would not be better to use a word likefinalize(tx)
? Although that also has connotations.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My idea behind the
close
was to implementjava.io.Closeable
so one can use try-with-resource. The problem here is that the index itself is not aware of the transaction, so the tx must be passed to each method as param- also to theclose
method. And so, with the additional parameter, it can no longer implementjava.io.Closeable
.What do you think about having a Transaction-Aware Facade that can be
Closable
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks sounds nice. Worth a try, as long as the transaction does not leak anywhere.