Skip to content

Commit 0ad6edd

Browse files
authored
Make spatial query procedures read only (#403)
1 parent 1b6fb88 commit 0ad6edd

File tree

8 files changed

+54
-12
lines changed

8 files changed

+54
-12
lines changed

src/main/java/org/neo4j/gis/spatial/EditableLayer.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,4 +59,9 @@ public interface EditableLayer extends Layer {
5959
void setCoordinateReferenceSystem(Transaction tx, CoordinateReferenceSystem coordinateReferenceSystem);
6060

6161
void removeFromIndex(Transaction tx, String geomNodeId);
62+
63+
/**
64+
* Do any cleanup or final calculation required by the layer implementation.
65+
*/
66+
void finalizeTransaction(Transaction tx);
6267
}

src/main/java/org/neo4j/gis/spatial/EditableLayerImpl.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,4 +81,9 @@ protected Node addGeomNode(Transaction tx, Geometry geom, String[] fieldsName, O
8181
public String getSignature() {
8282
return "Editable" + super.getSignature();
8383
}
84+
85+
@Override
86+
public void finalizeTransaction(Transaction tx) {
87+
getIndex().finalizeTransaction(tx);
88+
}
8489
}

src/main/java/org/neo4j/gis/spatial/ShapefileImporter.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,10 @@ record = shpReader.nextRecord();
220220
}
221221
}
222222
}
223+
try (Transaction tx = database.beginTx()) {
224+
layer.finalizeTransaction(tx);
225+
tx.commit();
226+
}
223227

224228
long stopTime = System.currentTimeMillis();
225229
log("info | elapsed time in seconds: " + (1.0 * (stopTime - startTime) / 1000));

src/main/java/org/neo4j/gis/spatial/index/SpatialIndexReader.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,7 @@ public interface SpatialIndexReader {
4747
void addMonitor(TreeMonitor monitor);
4848

4949
void configure(Map<String, Object> config);
50+
51+
default void finalizeTransaction(Transaction tx) {
52+
}
5053
}

src/main/java/org/neo4j/gis/spatial/osm/OSMImporter.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,7 @@ public long reIndex(GraphDatabaseService database, int commitInterval, boolean i
329329
}
330330
} // TODO ask charset to user?
331331
}
332+
layer.finalizeTransaction(tx);
332333
tx.commit();
333334
} finally {
334335
endProgressMonitor();

src/main/java/org/neo4j/gis/spatial/procedures/SpatialProcedures.java

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
package org.neo4j.gis.spatial.procedures;
2121

2222
import static org.neo4j.gis.spatial.SpatialDatabaseService.RTREE_INDEX_NAME;
23+
import static org.neo4j.procedure.Mode.READ;
2324
import static org.neo4j.procedure.Mode.WRITE;
2425

2526
import java.io.File;
@@ -182,7 +183,7 @@ public Stream<NameResult> upgradeSpatial() {
182183
return builder.build();
183184
}
184185

185-
@Procedure(value = "spatial.layers", mode = WRITE)
186+
@Procedure(value = "spatial.layers", mode = READ)
186187
@Description("Returns name, and details for all layers")
187188
public Stream<NameResult> getAllLayers() {
188189
SpatialDatabaseService sdb = spatial();
@@ -553,21 +554,27 @@ public void removeLayer(@Name("name") String name) {
553554
@Description("Adds the given node to the layer, returns the geometry-node")
554555
public Stream<NodeResult> addNodeToLayer(@Name("layerName") String name, @Name("node") Node node) {
555556
EditableLayer layer = getEditableLayerOrThrow(tx, spatial(), name);
556-
return streamNode(layer.add(tx, node).getGeomNode());
557+
Node geomNode = layer.add(tx, node).getGeomNode();
558+
layer.finalizeTransaction(tx);
559+
return streamNode(geomNode);
557560
}
558561

559562
@Procedure(value = "spatial.addNodes", mode = WRITE)
560563
@Description("Adds the given nodes list to the layer, returns the count")
561564
public Stream<CountResult> addNodesToLayer(@Name("layerName") String name, @Name("nodes") List<Node> nodes) {
562565
EditableLayer layer = getEditableLayerOrThrow(tx, spatial(), name);
563-
return Stream.of(new CountResult(layer.addAll(tx, nodes)));
566+
int count = layer.addAll(tx, nodes);
567+
layer.finalizeTransaction(tx);
568+
return Stream.of(new CountResult(count));
564569
}
565570

566571
@Procedure(value = "spatial.addNode.byId", mode = WRITE)
567572
@Description("Adds the given node to the layer, returns the geometry-node")
568573
public Stream<NodeResult> addNodeIdToLayer(@Name("layerName") String name, @Name("nodeId") String nodeId) {
569574
EditableLayer layer = getEditableLayerOrThrow(tx, spatial(), name);
570-
return streamNode(layer.add(tx, tx.getNodeByElementId(nodeId)).getGeomNode());
575+
Node geomNode = layer.add(tx, tx.getNodeByElementId(nodeId)).getGeomNode();
576+
layer.finalizeTransaction(tx);
577+
return streamNode(geomNode);
571578
}
572579

573580
@Procedure(value = "spatial.addNodes.byId", mode = WRITE)
@@ -576,14 +583,17 @@ public Stream<CountResult> addNodeIdsToLayer(@Name("layerName") String name,
576583
@Name("nodeIds") List<String> nodeIds) {
577584
EditableLayer layer = getEditableLayerOrThrow(tx, spatial(), name);
578585
List<Node> nodes = nodeIds.stream().map(id -> tx.getNodeByElementId(id)).collect(Collectors.toList());
579-
return Stream.of(new CountResult(layer.addAll(tx, nodes)));
586+
int count = layer.addAll(tx, nodes);
587+
layer.finalizeTransaction(tx);
588+
return Stream.of(new CountResult(count));
580589
}
581590

582591
@Procedure(value = "spatial.removeNode", mode = WRITE)
583592
@Description("Removes the given node from the layer, returns the geometry-node")
584593
public Stream<NodeIdResult> removeNodeFromLayer(@Name("layerName") String name, @Name("node") Node node) {
585594
EditableLayer layer = getEditableLayerOrThrow(tx, spatial(), name);
586595
layer.removeFromIndex(tx, node.getElementId());
596+
layer.finalizeTransaction(tx);
587597
return streamNode(node.getElementId());
588598
}
589599

@@ -597,6 +607,7 @@ public Stream<CountResult> removeNodesFromLayer(@Name("layerName") String name,
597607
layer.removeFromIndex(tx, node.getElementId());
598608
}
599609
int after = layer.getIndex().count(tx);
610+
layer.finalizeTransaction(tx);
600611
return Stream.of(new CountResult(before - after));
601612
}
602613

@@ -605,6 +616,7 @@ public Stream<CountResult> removeNodesFromLayer(@Name("layerName") String name,
605616
public Stream<NodeIdResult> removeNodeFromLayer(@Name("layerName") String name, @Name("nodeId") String nodeId) {
606617
EditableLayer layer = getEditableLayerOrThrow(tx, spatial(), name);
607618
layer.removeFromIndex(tx, nodeId);
619+
layer.finalizeTransaction(tx);
608620
return streamNode(nodeId);
609621
}
610622

@@ -619,6 +631,7 @@ public Stream<CountResult> removeNodeIdsFromLayer(@Name("layerName") String name
619631
layer.removeFromIndex(tx, nodeId);
620632
}
621633
int after = layer.getIndex().count(tx);
634+
layer.finalizeTransaction(tx);
622635
return Stream.of(new CountResult(before - after));
623636
}
624637

@@ -628,7 +641,9 @@ public Stream<NodeResult> addGeometryWKTToLayer(@Name("layerName") String name,
628641
@Name("geometry") String geometryWKT) {
629642
EditableLayer layer = getEditableLayerOrThrow(tx, spatial(), name);
630643
WKTReader reader = new WKTReader(layer.getGeometryFactory());
631-
return streamNode(addGeometryWkt(layer, reader, geometryWKT));
644+
Node node = addGeometryWkt(layer, reader, geometryWKT);
645+
layer.finalizeTransaction(tx);
646+
return streamNode(node);
632647
}
633648

634649
@Procedure(value = "spatial.addWKTs", mode = WRITE)
@@ -638,7 +653,8 @@ public Stream<NodeResult> addGeometryWKTsToLayer(@Name("layerName") String name,
638653
EditableLayer layer = getEditableLayerOrThrow(tx, spatial(), name);
639654
WKTReader reader = new WKTReader(layer.getGeometryFactory());
640655
return geometryWKTs.stream().map(geometryWKT -> addGeometryWkt(layer, reader, geometryWKT))
641-
.map(NodeResult::new);
656+
.map(NodeResult::new)
657+
.onClose(() -> layer.finalizeTransaction(tx));
642658
}
643659

644660
private Node addGeometryWkt(EditableLayer layer, WKTReader reader, String geometryWKT) {
@@ -656,7 +672,9 @@ public Stream<CountResult> importShapefile(
656672
@Name("layerName") String name,
657673
@Name("uri") String uri) throws IOException {
658674
EditableLayerImpl layer = getEditableLayerOrThrow(tx, spatial(), name);
659-
return Stream.of(new CountResult(importShapefileToLayer(uri, layer, 1000).size()));
675+
List<Node> nodes = importShapefileToLayer(uri, layer, 1000);
676+
layer.finalizeTransaction(tx);
677+
return Stream.of(new CountResult(nodes.size()));
660678
}
661679

662680
@Procedure(value = "spatial.importShapefile", mode = WRITE)
@@ -776,7 +794,7 @@ public void run() {
776794
}
777795
}
778796

779-
@Procedure(value = "spatial.bbox", mode = WRITE)
797+
@Procedure(value = "spatial.bbox", mode = READ)
780798
@Description("Finds all geometry nodes in the given layer within the lower left and upper right coordinates of a box")
781799
public Stream<NodeResult> findGeometriesInBBox(
782800
@Name("layerName") String name,
@@ -790,7 +808,7 @@ public Stream<NodeResult> findGeometriesInBBox(
790808
.stream().map(GeoPipeFlow::getGeomNode).map(NodeResult::new);
791809
}
792810

793-
@Procedure(value = "spatial.closest", mode = WRITE)
811+
@Procedure(value = "spatial.closest", mode = READ)
794812
@Description("Finds all geometry nodes in the layer within the distance to the given coordinate")
795813
public Stream<NodeResult> findClosestGeometries(
796814
@Name("layerName") String name,
@@ -804,7 +822,7 @@ public Stream<NodeResult> findClosestGeometries(
804822
return edgeResults.stream().map(e -> e.getValue().getGeomNode()).map(NodeResult::new);
805823
}
806824

807-
@Procedure(value = "spatial.withinDistance", mode = WRITE)
825+
@Procedure(value = "spatial.withinDistance", mode = READ)
808826
@Description("Returns all geometry nodes and their ordered distance in the layer within the distance to the given coordinate")
809827
public Stream<NodeDistanceResult> findGeometriesWithinDistance(
810828
@Name("layerName") String name,
@@ -841,7 +859,7 @@ public Stream<GeometryResult> asExternalGeometry(
841859
return Stream.of(geometry).map(geom -> new GeometryResult(toNeo4jGeometry(null, geom)));
842860
}
843861

844-
@Procedure(value = "spatial.intersects", mode = WRITE)
862+
@Procedure(value = "spatial.intersects", mode = READ)
845863
@Description("Returns all geometry nodes that intersect the given geometry (shape, polygon) in the layer")
846864
public Stream<NodeResult> findGeometriesIntersecting(
847865
@Name("layerName") String name,

src/main/java/org/neo4j/gis/spatial/rtree/RTreeIndex.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1554,4 +1554,9 @@ public int compare(NodeWithEnvelope o1, NodeWithEnvelope o2) {
15541554
return Double.compare(o1.envelope.getArea(), o2.envelope.getArea());
15551555
}
15561556
}
1557+
1558+
@Override
1559+
public void finalizeTransaction(Transaction tx) {
1560+
saveCount(tx);
1561+
}
15571562
}

src/test/java/org/neo4j/gis/spatial/LayersTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,7 @@ public void testIndexAccessAfterBulkInsertion() {
365365
coordinateNodes.add(node);
366366
}
367367
layer.addAll(tx, coordinateNodes);
368+
layer.finalizeTransaction(tx);
368369
tx.commit();
369370
}
370371

0 commit comments

Comments
 (0)