From 096204acc79e248cc3f25bdd7ed60eb84ad8a93f Mon Sep 17 00:00:00 2001 From: Sascha Peukert Date: Wed, 11 Jul 2018 14:23:40 +0200 Subject: [PATCH] Included feedback from Pontus - Revert change to toString of Point (for now) - Added SortedLabels to circumvent sorting all LabelSets - Other small refactorings --- .../neo4j/internal/kernel/api/LabelSet.java | 5 +- .../internal/kernel/api/helpers/NodeData.java | 33 ----- .../kernel/api/helpers/NodeDataTest.java | 66 ---------- .../kernel/builtinprocs/SchemaCalculator.java | 120 ++++++++++-------- .../kernel/builtinprocs/SortedLabels.java | 61 +++++++++ .../org/neo4j/kernel/impl/newapi/Labels.java | 31 +---- .../SortedLabelsTest.java} | 16 +-- .../org/neo4j/values/storable/PointValue.java | 6 +- .../SpatialFunctionsAcceptanceTest.scala | 4 +- 9 files changed, 145 insertions(+), 197 deletions(-) delete mode 100644 community/kernel-api/src/test/java/org/neo4j/internal/kernel/api/helpers/NodeDataTest.java create mode 100644 community/kernel/src/main/java/org/neo4j/kernel/builtinprocs/SortedLabels.java rename community/kernel/src/test/java/org/neo4j/kernel/{impl/newapi/LabelsTest.java => builtinprocs/SortedLabelsTest.java} (81%) diff --git a/community/kernel-api/src/main/java/org/neo4j/internal/kernel/api/LabelSet.java b/community/kernel-api/src/main/java/org/neo4j/internal/kernel/api/LabelSet.java index e72f2eaa5057..03cfde24a6cf 100644 --- a/community/kernel-api/src/main/java/org/neo4j/internal/kernel/api/LabelSet.java +++ b/community/kernel-api/src/main/java/org/neo4j/internal/kernel/api/LabelSet.java @@ -19,7 +19,6 @@ */ package org.neo4j.internal.kernel.api; -import java.util.Arrays; import java.util.NoSuchElementException; /** @@ -69,7 +68,7 @@ public long[] all() @Override public int hashCode() { - return Arrays.hashCode( EMPTY ); + return 1; } @Override @@ -77,7 +76,7 @@ public boolean equals( Object obj ) { if ( obj instanceof LabelSet ) { - return ((LabelSet) obj).all().length == 0; + return ((LabelSet) obj).numberOfLabels() == 0; } return false; } diff --git a/community/kernel-api/src/test/java/org/neo4j/internal/kernel/api/helpers/NodeData.java b/community/kernel-api/src/test/java/org/neo4j/internal/kernel/api/helpers/NodeData.java index 45fb1fc4a51a..77676967e581 100644 --- a/community/kernel-api/src/test/java/org/neo4j/internal/kernel/api/helpers/NodeData.java +++ b/community/kernel-api/src/test/java/org/neo4j/internal/kernel/api/helpers/NodeData.java @@ -19,7 +19,6 @@ */ package org.neo4j.internal.kernel.api.helpers; -import java.util.Arrays; import java.util.Map; import org.neo4j.internal.kernel.api.LabelSet; @@ -33,14 +32,9 @@ class NodeData NodeData( long id, long[] labels, Map properties ) { - if ( labels == null ) - { - throw new IllegalArgumentException(); - } this.id = id; this.labels = labels; - Arrays.sort( labels ); // needed for quick equality check, most of the time, its already sorted anyway this.properties = properties; } @@ -78,33 +72,6 @@ public long[] all() { return labels; } - - @Override - public int hashCode() - { - return Arrays.hashCode( labels ); - } - - @Override - public boolean equals( Object obj ) - { - if ( obj instanceof LabelSet ) - { - long[] input = ((LabelSet) obj).all(); - - if ( labels == input ) - { - return true; - } - if ( input.length != labels.length ) - { - return false; - } - - return Arrays.equals( labels, input ); - } - return false; - } }; } } diff --git a/community/kernel-api/src/test/java/org/neo4j/internal/kernel/api/helpers/NodeDataTest.java b/community/kernel-api/src/test/java/org/neo4j/internal/kernel/api/helpers/NodeDataTest.java deleted file mode 100644 index 7233e5a0f2c8..000000000000 --- a/community/kernel-api/src/test/java/org/neo4j/internal/kernel/api/helpers/NodeDataTest.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2002-2018 "Neo4j," - * Neo4j Sweden AB [http://neo4j.com] - * - * This file is part of Neo4j. - * - * Neo4j is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package org.neo4j.internal.kernel.api.helpers; - -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertTrue; - -public class NodeDataTest -{ - @Test - public void testEqualityOfLabelSets() - { - long[] longsA = new long[]{1L,2L,3L}; - long[] longsB = new long[]{3L,2L,1L}; - long[] longsC = new long[]{1L,2L,3L,4L}; - NodeData a = new NodeData( 1, longsA, null ); - NodeData b = new NodeData( 1, longsB, null ); - NodeData c = new NodeData( 1, longsC, null ); - - // self - assertTrue(a.labelSet().equals( a.labelSet() )); - - // unordered self - assertTrue(a.labelSet().equals( b.labelSet() )); - assertTrue(b.labelSet().equals( a.labelSet() )); - - // other - assertFalse(a.labelSet().equals( c.labelSet() )); - assertFalse(c.labelSet().equals( a.labelSet() )); - } - - @Test - public void testHashCodeOfLabelSet() - { - long[] longsA = new long[]{1L,2L,3L}; - long[] longsB = new long[]{3L,2L,1L}; - long[] longsC = new long[]{1L,2L,3L,4L}; - NodeData a = new NodeData( 1, longsA, null ); - NodeData b = new NodeData( 1, longsB, null ); - NodeData c = new NodeData( 1, longsC, null ); - - assertEquals( a.labelSet().hashCode(), b.labelSet().hashCode() ); - assertNotEquals( a.labelSet().hashCode(), c.labelSet().hashCode() ); - } -} diff --git a/community/kernel/src/main/java/org/neo4j/kernel/builtinprocs/SchemaCalculator.java b/community/kernel/src/main/java/org/neo4j/kernel/builtinprocs/SchemaCalculator.java index 1d716aae8681..43bc1ee3c917 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/builtinprocs/SchemaCalculator.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/builtinprocs/SchemaCalculator.java @@ -31,7 +31,6 @@ import org.neo4j.helpers.collection.Pair; import org.neo4j.internal.kernel.api.CursorFactory; -import org.neo4j.internal.kernel.api.LabelSet; import org.neo4j.internal.kernel.api.NamedToken; import org.neo4j.internal.kernel.api.NodeCursor; import org.neo4j.internal.kernel.api.PropertyCursor; @@ -51,10 +50,8 @@ public class SchemaCalculator { - private org.neo4j.internal.kernel.api.Transaction ktx; - - private Map> labelSetToPropertyKeysMapping; - private Map,ValueTypeDecider> labelSetANDNodePropertyKeyIdToValueTypeMapping; + private Map> labelSetToPropertyKeysMapping; + private Map,ValueTypeDecider> labelSetANDNodePropertyKeyIdToValueTypeMapping; private Map labelIdToLabelNameMapping; private Map propertyIdToPropertylNameMapping; private Map relationshipTypIdToRelationshipNameMapping; @@ -62,23 +59,30 @@ public class SchemaCalculator private Map,ValueTypeDecider> relationshipTypeIdANDPropertyTypeIdToValueTypeMapping; private final Set emptyPropertyIdSet = Collections.unmodifiableSet( Collections.emptySet() ); - private final String ANYVALUE = "ANY"; - private final String INTEGRAL = "INTEGRAL"; - private final String INTEGRAL_ARRAY = "INTEGRALARRAY"; - private final String FLOATING_POINT = "FLOATINGPOINT"; - private final String FLOATING_POINT_ARRAY = "FLOATINGPOINTARRAY"; - private final String NULLABLE = "?"; - private final String NULLABLE_ANYVALUE = ANYVALUE + NULLABLE; - private final String NULLABLE_INTEGRAL = INTEGRAL + NULLABLE; - private final String NULLABLE_INTEGRAL_ARRAY = INTEGRAL_ARRAY + NULLABLE; - private final String NULLABLE_FLOATING_POINT_ARRAY = FLOATING_POINT_ARRAY + NULLABLE; - private final String NULLABLE_FLOATING_POINT = FLOATING_POINT + NULLABLE; - private final String NODE = "Node"; - private final String RELATIONSHIP = "Relationship"; + private static final String NODE = "Node"; + private static final String RELATIONSHIP = "Relationship"; + private static final String NULLABLE = "?"; + + private final Read dataRead; + private final TokenRead tokenRead; + private final CursorFactory cursors; SchemaCalculator( Transaction ktx ) { - this.ktx = ktx; + dataRead = ktx.dataRead(); + tokenRead = ktx.tokenRead(); + cursors = ktx.cursors(); + + // setup mappings + int labelCount = tokenRead.labelCount(); + int relationshipTypeCount = tokenRead.relationshipTypeCount(); + labelSetToPropertyKeysMapping = new HashMap<>( labelCount ); + labelIdToLabelNameMapping = new HashMap<>( labelCount ); + propertyIdToPropertylNameMapping = new HashMap<>( tokenRead.propertyKeyCount() ); + relationshipTypIdToRelationshipNameMapping = new HashMap<>( relationshipTypeCount ); + relationshipTypeIdToPropertyKeysMapping = new HashMap<>( relationshipTypeCount ); + labelSetANDNodePropertyKeyIdToValueTypeMapping = new HashMap<>(); + relationshipTypeIdANDPropertyTypeIdToValueTypeMapping = new HashMap<>(); } public Stream calculateTabularResultStream() @@ -122,7 +126,7 @@ private List produceResultsForRelationships() private List produceResultsForNodes() { List results = new ArrayList<>(); - for ( LabelSet labelSet : labelSetToPropertyKeysMapping.keySet() ) + for ( SortedLabels labelSet : labelSetToPropertyKeysMapping.keySet() ) { // lookup label names and produce list of names List labelNames = new ArrayList<>(); @@ -154,24 +158,8 @@ private List produceResultsForNodes() //TODO: If we would have this schema information in the count store (or somewhere), this could be super fast private void calculateSchema() { - // this one does most of the work - Read dataRead = ktx.dataRead(); - TokenRead tokenRead = ktx.tokenRead(); - CursorFactory cursors = ktx.cursors(); - - // setup mappings - int labelCount = tokenRead.labelCount(); - int relationshipTypeCount = tokenRead.relationshipTypeCount(); - labelSetToPropertyKeysMapping = new HashMap<>( labelCount ); - labelIdToLabelNameMapping = new HashMap<>( labelCount ); - propertyIdToPropertylNameMapping = new HashMap<>( tokenRead.propertyKeyCount() ); - relationshipTypIdToRelationshipNameMapping = new HashMap<>( relationshipTypeCount ); - relationshipTypeIdToPropertyKeysMapping = new HashMap<>( relationshipTypeCount ); - labelSetANDNodePropertyKeyIdToValueTypeMapping = new HashMap<>(); - relationshipTypeIdANDPropertyTypeIdToValueTypeMapping = new HashMap<>(); - - scanEverythingBelongingToNodes( dataRead, cursors ); - scanEverythingBelongingToRelationships( dataRead, cursors ); + scanEverythingBelongingToNodes(); + scanEverythingBelongingToRelationships(); // OTHER: // go through all labels @@ -182,7 +170,7 @@ private void calculateSchema() addNamesToCollection( tokenRead.relationshipTypesGetAllTokens(), relationshipTypIdToRelationshipNameMapping ); } - private void scanEverythingBelongingToRelationships( Read dataRead, CursorFactory cursors ) + private void scanEverythingBelongingToRelationships() { try ( RelationshipScanCursor relationshipScanCursor = cursors.allocateRelationshipScanCursor(); PropertyCursor propertyCursor = cursors.allocatePropertyCursor() ) @@ -226,7 +214,7 @@ private void scanEverythingBelongingToRelationships( Read dataRead, CursorFactor } } - private void scanEverythingBelongingToNodes( Read dataRead, CursorFactory cursors ) + private void scanEverythingBelongingToNodes() { try ( NodeCursor nodeCursor = cursors.allocateNodeCursor(); PropertyCursor propertyCursor = cursors.allocatePropertyCursor() ) @@ -235,7 +223,7 @@ private void scanEverythingBelongingToNodes( Read dataRead, CursorFactory cursor while ( nodeCursor.next() ) { // each node - LabelSet labels = nodeCursor.labels(); + SortedLabels labels = SortedLabels.from( nodeCursor.labels() ); nodeCursor.properties( propertyCursor ); Set propertyIds = new HashSet<>(); @@ -243,7 +231,7 @@ private void scanEverythingBelongingToNodes( Read dataRead, CursorFactory cursor { Value currentValue = propertyCursor.propertyValue(); int propertyKeyId = propertyCursor.propertyKey(); - Pair key = Pair.of( labels, propertyKeyId ); + Pair key = Pair.of( labels, propertyKeyId ); updateValueTypeInMapping( currentValue, key, labelSetANDNodePropertyKeyIdToValueTypeMapping ); propertyIds.add( propertyKeyId ); @@ -258,7 +246,7 @@ private void scanEverythingBelongingToNodes( Read dataRead, CursorFactory cursor // we can and need (!) to skip this if we found the empty set oldPropertyKeySet.removeAll( propertyIds ); oldPropertyKeySet.forEach( id -> { - Pair key = Pair.of( labels, id ); + Pair key = Pair.of( labels, id ); labelSetANDNodePropertyKeyIdToValueTypeMapping.get( key ).setNullable(); } ); } @@ -358,33 +346,33 @@ String getCypherTypeString() { if ( isIntegral ) { - return isNullable ? NULLABLE_INTEGRAL - : INTEGRAL; + return isNullable ? ValueName.NULLABLE_INTEGRAL.asString() + : ValueName.INTEGRAL.asString(); } else { - return isNullable ? NULLABLE_FLOATING_POINT - : FLOATING_POINT; + return isNullable ? ValueName.NULLABLE_FLOATING_POINT.asString() + : ValueName.FLOATING_POINT.asString(); } } // NUMBER_ARRAY if ( isIntegral ) { - return isNullable ? NULLABLE_INTEGRAL_ARRAY - : INTEGRAL_ARRAY; + return isNullable ? ValueName.NULLABLE_INTEGRAL_ARRAY.asString() + : ValueName.INTEGRAL_ARRAY.asString(); } else { - return isNullable ? NULLABLE_FLOATING_POINT_ARRAY - : FLOATING_POINT_ARRAY; + return isNullable ? ValueName.NULLABLE_FLOATING_POINT_ARRAY.asString() + : ValueName.FLOATING_POINT_ARRAY.asString(); } case VALUE_GROUP: return isNullable ? valueGroup.name() + NULLABLE : valueGroup.name(); case ANY: - return isNullable ? NULLABLE_ANYVALUE - : ANYVALUE; + return isNullable ? ValueName.NULLABLE_ANYVALUE.asString() + : ValueName.ANYVALUE.asString(); default: throw new IllegalStateException( "Did not recognize ValueStatus" ); } @@ -484,4 +472,30 @@ enum ValueStatus VALUE_GROUP, ANY } + + enum ValueName + { + ANYVALUE( "ANY" ), + INTEGRAL( "INTEGRAL" ), + INTEGRAL_ARRAY( "INTEGRALARRAY" ), + FLOATING_POINT( "FLOATINGPOINT" ), + FLOATING_POINT_ARRAY( "FLOATINGPOINTARRAY" ), + NULLABLE_ANYVALUE( ANYVALUE.asString() + NULLABLE ), + NULLABLE_INTEGRAL( INTEGRAL.asString() + NULLABLE ), + NULLABLE_INTEGRAL_ARRAY( INTEGRAL_ARRAY.asString() + NULLABLE ), + NULLABLE_FLOATING_POINT_ARRAY( FLOATING_POINT_ARRAY.asString() + NULLABLE ), + NULLABLE_FLOATING_POINT( FLOATING_POINT.asString() + NULLABLE ); + + private final String textRepresentation; + + ValueName( String textRepresentation ) + { + this.textRepresentation = textRepresentation; + } + + String asString() + { + return textRepresentation; + } + } } diff --git a/community/kernel/src/main/java/org/neo4j/kernel/builtinprocs/SortedLabels.java b/community/kernel/src/main/java/org/neo4j/kernel/builtinprocs/SortedLabels.java new file mode 100644 index 000000000000..e72d0753b0c1 --- /dev/null +++ b/community/kernel/src/main/java/org/neo4j/kernel/builtinprocs/SortedLabels.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2002-2018 "Neo4j," + * Neo4j Sweden AB [http://neo4j.com] + * + * This file is part of Neo4j. + * + * Neo4j is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.neo4j.kernel.builtinprocs; + +import java.util.Arrays; + +import org.neo4j.internal.kernel.api.LabelSet; +import org.neo4j.kernel.impl.newapi.Labels; + +public class SortedLabels extends Labels +{ + private SortedLabels( long[] labels ) + { + super( labels ); + } + + public static SortedLabels from( long[] labels ) + { + Arrays.sort( labels ); + return new SortedLabels( labels ); + } + + static SortedLabels from( LabelSet labelSet ) + { + return from( labelSet.all() ); + } + + @Override + public int hashCode() + { + return Arrays.hashCode( labels ); + } + + @Override + public boolean equals( Object obj ) + { + if ( obj instanceof LabelSet ) + { + long[] input = ((LabelSet) obj).all(); + return Arrays.equals( labels, input ); + } + return false; + } +} diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/newapi/Labels.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/newapi/Labels.java index cf9af99907f8..b930c6857f3f 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/newapi/Labels.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/newapi/Labels.java @@ -32,9 +32,9 @@ public class Labels implements LabelSet * This really only needs to be {@code int[]}, but the underlying implementation uses {@code long[]} for some * reason. */ - private final long[] labels; + protected final long[] labels; - private Labels( long[] labels ) + protected Labels( long[] labels ) { this.labels = labels; Arrays.sort(labels); // needed for quick equality check, most of the time, its already sorted anyway @@ -107,31 +107,4 @@ public long[] all() { return labels; } - - @Override - public int hashCode() - { - return Arrays.hashCode( labels ); - } - - @Override - public boolean equals( Object obj ) - { - if ( obj instanceof LabelSet ) - { - long[] input = ((LabelSet) obj).all(); - - if ( labels == input ) - { - return true; - } - if ( input.length != labels.length ) - { - return false; - } - - return Arrays.equals( labels, input ); - } - return false; - } } diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/newapi/LabelsTest.java b/community/kernel/src/test/java/org/neo4j/kernel/builtinprocs/SortedLabelsTest.java similarity index 81% rename from community/kernel/src/test/java/org/neo4j/kernel/impl/newapi/LabelsTest.java rename to community/kernel/src/test/java/org/neo4j/kernel/builtinprocs/SortedLabelsTest.java index 211cca15b289..27058420ee06 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/newapi/LabelsTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/builtinprocs/SortedLabelsTest.java @@ -17,7 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package org.neo4j.kernel.impl.newapi; +package org.neo4j.kernel.builtinprocs; import org.junit.Test; @@ -26,7 +26,7 @@ import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertTrue; -public class LabelsTest +public class SortedLabelsTest { @Test public void testEquals() @@ -34,9 +34,9 @@ public void testEquals() long[] longsA = new long[]{1L, 2L, 3L}; long[] longsB = new long[]{3L, 2L, 1L}; long[] longsC = new long[]{1L, 2L, 3L, 4L}; - Labels a = Labels.from( longsA ); - Labels b = Labels.from( longsB ); - Labels c = Labels.from( longsC ); + SortedLabels a = SortedLabels.from( longsA ); + SortedLabels b = SortedLabels.from( longsB ); + SortedLabels c = SortedLabels.from( longsC ); // self //noinspection EqualsWithItself @@ -57,9 +57,9 @@ public void testHashCodeOfLabelSet() long[] longsA = new long[]{1L,2L,3L}; long[] longsB = new long[]{3L,2L,1L}; long[] longsC = new long[]{1L,2L,3L,4L}; - Labels a = Labels.from( longsA ); - Labels b = Labels.from( longsB ); - Labels c = Labels.from( longsC ); + SortedLabels a = SortedLabels.from( longsA ); + SortedLabels b = SortedLabels.from( longsB ); + SortedLabels c = SortedLabels.from( longsC ); assertEquals( a.hashCode(), b.hashCode() ); assertNotEquals( a.hashCode(), c.hashCode() ); diff --git a/community/values/src/main/java/org/neo4j/values/storable/PointValue.java b/community/values/src/main/java/org/neo4j/values/storable/PointValue.java index a6973a2dc2f2..30bda176e3f1 100644 --- a/community/values/src/main/java/org/neo4j/values/storable/PointValue.java +++ b/community/values/src/main/java/org/neo4j/values/storable/PointValue.java @@ -235,9 +235,9 @@ public T map( ValueMapper mapper ) @Override public String toString() { - String coordString = coordinate.length == 2 ? format( "x: %s, y: %s", coordinate[0], coordinate[1] ) : - format( "x: %s, y: %s, z: %s", coordinate[0], coordinate[1], coordinate[2] ); - return format( "%s({%s, crs: '%s'})", getTypeName(), coordString, getCoordinateReferenceSystem().getName() ); + String coordString = coordinate.length == 2 ? format( "x: %s, y: %s", coordinate[0], coordinate[1] ) + : format( "x: %s, y: %s, z: %s", coordinate[0], coordinate[1], coordinate[2] ); + return format( "point({%s, crs: '%s'})", coordString, getCoordinateReferenceSystem().getName() ); //TODO: Use getTypeName -> Breaking change } @Override diff --git a/enterprise/cypher/acceptance-spec-suite/src/test/scala/org/neo4j/internal/cypher/acceptance/SpatialFunctionsAcceptanceTest.scala b/enterprise/cypher/acceptance-spec-suite/src/test/scala/org/neo4j/internal/cypher/acceptance/SpatialFunctionsAcceptanceTest.scala index 5bfd30322d1b..4d3800bbd025 100644 --- a/enterprise/cypher/acceptance-spec-suite/src/test/scala/org/neo4j/internal/cypher/acceptance/SpatialFunctionsAcceptanceTest.scala +++ b/enterprise/cypher/acceptance-spec-suite/src/test/scala/org/neo4j/internal/cypher/acceptance/SpatialFunctionsAcceptanceTest.scala @@ -35,8 +35,8 @@ class SpatialFunctionsAcceptanceTest extends ExecutionEngineFunSuite with Cypher private val latestPointConfig = Configs.Interpreted - Configs.BackwardsCompatibility - Configs.AllRulePlanners test("toString on points") { - executeWith(latestPointConfig, "RETURN toString(point({x:1, y:2})) AS s").toList should equal(List(Map("s" -> "Point({x: 1.0, y: 2.0, crs: 'cartesian'})"))) - executeWith(latestPointConfig, "RETURN toString(point({longitude:1, latitude:2, height:3})) AS s").toList should equal(List(Map("s" -> "Point({x: 1.0, y: 2.0, z: 3.0, crs: 'wgs-84-3d'})"))) + executeWith(latestPointConfig, "RETURN toString(point({x:1, y:2})) AS s").toList should equal(List(Map("s" -> "point({x: 1.0, y: 2.0, crs: 'cartesian'})"))) + executeWith(latestPointConfig, "RETURN toString(point({longitude:1, latitude:2, height:3})) AS s").toList should equal(List(Map("s" -> "point({x: 1.0, y: 2.0, z: 3.0, crs: 'wgs-84-3d'})"))) } test("point function should work with literal map") {