Skip to content

Commit 0be5527

Browse files
committed
Make spatial query procedures read only
1 parent 68a0859 commit 0be5527

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 close(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 close(Transaction tx) {
87+
getIndex().close(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.close(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 close(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.close(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();
@@ -521,21 +522,27 @@ public void removeLayer(@Name("name") String name) {
521522
@Description("Adds the given node to the layer, returns the geometry-node")
522523
public Stream<NodeResult> addNodeToLayer(@Name("layerName") String name, @Name("node") Node node) {
523524
EditableLayer layer = getEditableLayerOrThrow(tx, spatial(), name);
524-
return streamNode(layer.add(tx, node).getGeomNode());
525+
Node geomNode = layer.add(tx, node).getGeomNode();
526+
layer.close(tx);
527+
return streamNode(geomNode);
525528
}
526529

527530
@Procedure(value = "spatial.addNodes", mode = WRITE)
528531
@Description("Adds the given nodes list to the layer, returns the count")
529532
public Stream<CountResult> addNodesToLayer(@Name("layerName") String name, @Name("nodes") List<Node> nodes) {
530533
EditableLayer layer = getEditableLayerOrThrow(tx, spatial(), name);
531-
return Stream.of(new CountResult(layer.addAll(tx, nodes)));
534+
int count = layer.addAll(tx, nodes);
535+
layer.close(tx);
536+
return Stream.of(new CountResult(count));
532537
}
533538

534539
@Procedure(value = "spatial.addNode.byId", mode = WRITE)
535540
@Description("Adds the given node to the layer, returns the geometry-node")
536541
public Stream<NodeResult> addNodeIdToLayer(@Name("layerName") String name, @Name("nodeId") String nodeId) {
537542
EditableLayer layer = getEditableLayerOrThrow(tx, spatial(), name);
538-
return streamNode(layer.add(tx, tx.getNodeByElementId(nodeId)).getGeomNode());
543+
Node geomNode = layer.add(tx, tx.getNodeByElementId(nodeId)).getGeomNode();
544+
layer.close(tx);
545+
return streamNode(geomNode);
539546
}
540547

541548
@Procedure(value = "spatial.addNodes.byId", mode = WRITE)
@@ -544,14 +551,17 @@ public Stream<CountResult> addNodeIdsToLayer(@Name("layerName") String name,
544551
@Name("nodeIds") List<String> nodeIds) {
545552
EditableLayer layer = getEditableLayerOrThrow(tx, spatial(), name);
546553
List<Node> nodes = nodeIds.stream().map(id -> tx.getNodeByElementId(id)).collect(Collectors.toList());
547-
return Stream.of(new CountResult(layer.addAll(tx, nodes)));
554+
int count = layer.addAll(tx, nodes);
555+
layer.close(tx);
556+
return Stream.of(new CountResult(count));
548557
}
549558

550559
@Procedure(value = "spatial.removeNode", mode = WRITE)
551560
@Description("Removes the given node from the layer, returns the geometry-node")
552561
public Stream<NodeIdResult> removeNodeFromLayer(@Name("layerName") String name, @Name("node") Node node) {
553562
EditableLayer layer = getEditableLayerOrThrow(tx, spatial(), name);
554563
layer.removeFromIndex(tx, node.getElementId());
564+
layer.close(tx);
555565
return streamNode(node.getElementId());
556566
}
557567

@@ -565,6 +575,7 @@ public Stream<CountResult> removeNodesFromLayer(@Name("layerName") String name,
565575
layer.removeFromIndex(tx, node.getElementId());
566576
}
567577
int after = layer.getIndex().count(tx);
578+
layer.close(tx);
568579
return Stream.of(new CountResult(before - after));
569580
}
570581

@@ -573,6 +584,7 @@ public Stream<CountResult> removeNodesFromLayer(@Name("layerName") String name,
573584
public Stream<NodeIdResult> removeNodeFromLayer(@Name("layerName") String name, @Name("nodeId") String nodeId) {
574585
EditableLayer layer = getEditableLayerOrThrow(tx, spatial(), name);
575586
layer.removeFromIndex(tx, nodeId);
587+
layer.close(tx);
576588
return streamNode(nodeId);
577589
}
578590

@@ -587,6 +599,7 @@ public Stream<CountResult> removeNodeIdsFromLayer(@Name("layerName") String name
587599
layer.removeFromIndex(tx, nodeId);
588600
}
589601
int after = layer.getIndex().count(tx);
602+
layer.close(tx);
590603
return Stream.of(new CountResult(before - after));
591604
}
592605

@@ -596,7 +609,9 @@ public Stream<NodeResult> addGeometryWKTToLayer(@Name("layerName") String name,
596609
@Name("geometry") String geometryWKT) {
597610
EditableLayer layer = getEditableLayerOrThrow(tx, spatial(), name);
598611
WKTReader reader = new WKTReader(layer.getGeometryFactory());
599-
return streamNode(addGeometryWkt(layer, reader, geometryWKT));
612+
Node node = addGeometryWkt(layer, reader, geometryWKT);
613+
layer.close(tx);
614+
return streamNode(node);
600615
}
601616

602617
@Procedure(value = "spatial.addWKTs", mode = WRITE)
@@ -606,7 +621,8 @@ public Stream<NodeResult> addGeometryWKTsToLayer(@Name("layerName") String name,
606621
EditableLayer layer = getEditableLayerOrThrow(tx, spatial(), name);
607622
WKTReader reader = new WKTReader(layer.getGeometryFactory());
608623
return geometryWKTs.stream().map(geometryWKT -> addGeometryWkt(layer, reader, geometryWKT))
609-
.map(NodeResult::new);
624+
.map(NodeResult::new)
625+
.onClose(() -> layer.close(tx));
610626
}
611627

612628
private Node addGeometryWkt(EditableLayer layer, WKTReader reader, String geometryWKT) {
@@ -624,7 +640,9 @@ public Stream<CountResult> importShapefile(
624640
@Name("layerName") String name,
625641
@Name("uri") String uri) throws IOException {
626642
EditableLayerImpl layer = getEditableLayerOrThrow(tx, spatial(), name);
627-
return Stream.of(new CountResult(importShapefileToLayer(uri, layer, 1000).size()));
643+
List<Node> nodes = importShapefileToLayer(uri, layer, 1000);
644+
layer.close(tx);
645+
return Stream.of(new CountResult(nodes.size()));
628646
}
629647

630648
@Procedure(value = "spatial.importShapefile", mode = WRITE)
@@ -744,7 +762,7 @@ public void run() {
744762
}
745763
}
746764

747-
@Procedure(value = "spatial.bbox", mode = WRITE)
765+
@Procedure(value = "spatial.bbox", mode = READ)
748766
@Description("Finds all geometry nodes in the given layer within the lower left and upper right coordinates of a box")
749767
public Stream<NodeResult> findGeometriesInBBox(
750768
@Name("layerName") String name,
@@ -758,7 +776,7 @@ public Stream<NodeResult> findGeometriesInBBox(
758776
.stream().map(GeoPipeFlow::getGeomNode).map(NodeResult::new);
759777
}
760778

761-
@Procedure(value = "spatial.closest", mode = WRITE)
779+
@Procedure(value = "spatial.closest", mode = READ)
762780
@Description("Finds all geometry nodes in the layer within the distance to the given coordinate")
763781
public Stream<NodeResult> findClosestGeometries(
764782
@Name("layerName") String name,
@@ -772,7 +790,7 @@ public Stream<NodeResult> findClosestGeometries(
772790
return edgeResults.stream().map(e -> e.getValue().getGeomNode()).map(NodeResult::new);
773791
}
774792

775-
@Procedure(value = "spatial.withinDistance", mode = WRITE)
793+
@Procedure(value = "spatial.withinDistance", mode = READ)
776794
@Description("Returns all geometry nodes and their ordered distance in the layer within the distance to the given coordinate")
777795
public Stream<NodeDistanceResult> findGeometriesWithinDistance(
778796
@Name("layerName") String name,
@@ -809,7 +827,7 @@ public Stream<GeometryResult> asExternalGeometry(
809827
return Stream.of(geometry).map(geom -> new GeometryResult(toNeo4jGeometry(null, geom)));
810828
}
811829

812-
@Procedure(value = "spatial.intersects", mode = WRITE)
830+
@Procedure(value = "spatial.intersects", mode = READ)
813831
@Description("Returns all geometry nodes that intersect the given geometry (shape, polygon) in the layer")
814832
public Stream<NodeResult> findGeometriesIntersecting(
815833
@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
@@ -1544,4 +1544,9 @@ public int compare(NodeWithEnvelope o1, NodeWithEnvelope o2) {
15441544
return Double.compare(o1.envelope.getArea(), o2.envelope.getArea());
15451545
}
15461546
}
1547+
1548+
@Override
1549+
public void close(Transaction tx) {
1550+
saveCount(tx);
1551+
}
15471552
}

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.close(tx);
368369
tx.commit();
369370
}
370371

0 commit comments

Comments
 (0)