From 69ac7454d1434ad364f7c92968ef59c7757d47d4 Mon Sep 17 00:00:00 2001 From: Sascha Peukert Date: Fri, 8 Jun 2018 15:06:10 +0200 Subject: [PATCH] Started working on adding new schema procedure Added method to get common type name to values. Made LabelSet able to be used as key in HashMaps. --- .../neo4j/internal/kernel/api/LabelSet.java | 17 ++ .../internal/kernel/api/helpers/NodeData.java | 17 ++ .../builtinprocs/BuiltInSchemaProcedures.java | 83 ++++++ .../kernel/builtinprocs/SchemaCalculator.java | 240 ++++++++++++++++++ .../org/neo4j/kernel/impl/newapi/Labels.java | 16 ++ .../builtinprocs/BuiltInProceduresTest.java | 1 + .../BuiltInSchemaProceduresIT.java | 171 +++++++++++++ .../neo4j/values/storable/BooleanArray.java | 8 +- .../neo4j/values/storable/BooleanValue.java | 10 +- .../org/neo4j/values/storable/ByteArray.java | 8 +- .../org/neo4j/values/storable/ByteValue.java | 8 +- .../org/neo4j/values/storable/CharArray.java | 8 +- .../org/neo4j/values/storable/CharValue.java | 8 +- .../org/neo4j/values/storable/DateArray.java | 6 + .../neo4j/values/storable/DateTimeArray.java | 6 + .../neo4j/values/storable/DateTimeValue.java | 6 + .../org/neo4j/values/storable/DateValue.java | 6 + .../neo4j/values/storable/DoubleArray.java | 9 +- .../neo4j/values/storable/DoubleValue.java | 8 +- .../neo4j/values/storable/DurationArray.java | 6 + .../neo4j/values/storable/DurationValue.java | 6 + .../org/neo4j/values/storable/FloatArray.java | 8 +- .../org/neo4j/values/storable/FloatValue.java | 8 +- .../org/neo4j/values/storable/IntArray.java | 6 + .../org/neo4j/values/storable/IntValue.java | 6 + .../values/storable/LocalDateTimeArray.java | 6 + .../values/storable/LocalDateTimeValue.java | 6 + .../neo4j/values/storable/LocalTimeArray.java | 6 + .../neo4j/values/storable/LocalTimeValue.java | 6 + .../org/neo4j/values/storable/LongArray.java | 8 +- .../org/neo4j/values/storable/LongValue.java | 8 +- .../org/neo4j/values/storable/NoValue.java | 6 + .../org/neo4j/values/storable/PointArray.java | 6 + .../org/neo4j/values/storable/PointValue.java | 8 +- .../org/neo4j/values/storable/ShortArray.java | 8 +- .../org/neo4j/values/storable/ShortValue.java | 8 +- .../neo4j/values/storable/StringArray.java | 8 +- .../neo4j/values/storable/StringValue.java | 8 +- .../org/neo4j/values/storable/TimeArray.java | 6 + .../org/neo4j/values/storable/TimeValue.java | 6 + .../java/org/neo4j/values/storable/Value.java | 2 + 41 files changed, 763 insertions(+), 19 deletions(-) create mode 100644 community/kernel/src/main/java/org/neo4j/kernel/builtinprocs/BuiltInSchemaProcedures.java create mode 100644 community/kernel/src/main/java/org/neo4j/kernel/builtinprocs/SchemaCalculator.java create mode 100644 community/kernel/src/test/java/org/neo4j/kernel/impl/api/integrationtest/BuiltInSchemaProceduresIT.java 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 80a2e5269d014..e72f2eaa5057b 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,6 +19,7 @@ */ package org.neo4j.internal.kernel.api; +import java.util.Arrays; import java.util.NoSuchElementException; /** @@ -64,5 +65,21 @@ public long[] all() { return EMPTY; } + + @Override + public int hashCode() + { + return Arrays.hashCode( EMPTY ); + } + + @Override + public boolean equals( Object obj ) + { + if ( obj instanceof LabelSet ) + { + return ((LabelSet) obj).all().length == 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 aa8c6c0fbecf6..afa3fe79ab1cf 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,6 +19,7 @@ */ package org.neo4j.internal.kernel.api.helpers; +import java.util.Arrays; import java.util.Map; import org.neo4j.internal.kernel.api.LabelSet; @@ -71,6 +72,22 @@ public long[] all() { return labels; } + + @Override + public int hashCode() + { + return Arrays.hashCode( labels ); + } + + @Override + public boolean equals( Object obj ) + { + if ( obj instanceof LabelSet ) + { + return Arrays.equals( labels, ((LabelSet) obj).all() ); + } + return false; + } }; } } diff --git a/community/kernel/src/main/java/org/neo4j/kernel/builtinprocs/BuiltInSchemaProcedures.java b/community/kernel/src/main/java/org/neo4j/kernel/builtinprocs/BuiltInSchemaProcedures.java new file mode 100644 index 0000000000000..cad05018cf701 --- /dev/null +++ b/community/kernel/src/main/java/org/neo4j/kernel/builtinprocs/BuiltInSchemaProcedures.java @@ -0,0 +1,83 @@ +/* + * 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.List; +import java.util.stream.Stream; + +import org.neo4j.kernel.api.KernelTransaction; +import org.neo4j.kernel.internal.GraphDatabaseAPI; +import org.neo4j.procedure.Context; +import org.neo4j.procedure.Description; +import org.neo4j.procedure.Mode; +import org.neo4j.procedure.Procedure; + +public class BuiltInSchemaProcedures +{ + @Context + public GraphDatabaseAPI db; + + @Context + public KernelTransaction tx; + + @Procedure( name = "db.schemaAsTable", mode = Mode.READ ) + @Description( "Show the schema of the data in tabular form." ) + public Stream schemaAsTable() + { + return new SchemaCalculator( db, tx ).calculateTabularResultStream(); + } + + // TODO: Next step +// @Procedure( value = "db.schema.graph", mode = Mode.READ ) // TODO: Change to db.schema when ready to completly replace old one +// @Description( "Show the schema of the data." ) // old description +// public Stream schemaAsGraph() //TODO: Maybe extract inner result classes +// { +// return new SchemaCalculator( db, tx ).calculateGraphResultStream(); +// } + + public static class SchemaInfoResult + { + /** + * Indicates whether the entry is a node or a relationship + */ + public final String type; + /** + * A combination of labels or a relationship + */ + public final List nodeLabelsOrRelType; + /** + * A property that occurs on the given label combination / relationship type + */ + public final String property; + /** + * The CypherType of the given property on the given label combination / relationship type + */ + public final String cypherType; + + public SchemaInfoResult( String type, List nodeLabelsOrRelType, String property, String cypherType ) + { + this.type = type; + this.nodeLabelsOrRelType = nodeLabelsOrRelType; + this.property = property; + this.cypherType = cypherType; + } + } +} 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 new file mode 100644 index 0000000000000..8f84aec753d0a --- /dev/null +++ b/community/kernel/src/main/java/org/neo4j/kernel/builtinprocs/SchemaCalculator.java @@ -0,0 +1,240 @@ +/* + * 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 com.google.common.collect.HashBasedTable; +import com.google.common.collect.Table; +import sun.reflect.generics.reflectiveObjects.NotImplementedException; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Stream; + +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; +import org.neo4j.internal.kernel.api.Read; +import org.neo4j.internal.kernel.api.SchemaRead; +import org.neo4j.internal.kernel.api.TokenRead; +import org.neo4j.kernel.api.KernelTransaction; +import org.neo4j.kernel.api.Statement; +import org.neo4j.kernel.internal.GraphDatabaseAPI; +import org.neo4j.values.storable.Value; +import org.neo4j.values.storable.ValueGroup; + +public class SchemaCalculator +{ + private GraphDatabaseAPI db; + private KernelTransaction ktx; + + private Map> labelSetToPropertyKeysMapping; + // TODO: make those different Set etc. into more useful/understandable classes?! + private Table labelSetAndNodePropertyKeyIdToValueTypeMapping; // Dislike object here... + private Map labelIdToLabelNameMapping; + private Map propertyIdToPropertylNameMapping; + + private final Set emptyPropertyIdSet = Collections.unmodifiableSet( Collections.emptySet() ); + + private final String ANYVALUE = "ANYVALUE"; + private final String NODE = "Node"; + private final String RELATIONSHIP = "Relationship"; + + //TODO: Change Table to Pair! + //TODO: Remove Guava from pom + + public SchemaCalculator( GraphDatabaseAPI db, KernelTransaction ktx ) + { + this.db = db; + this.ktx = ktx; + labelSetAndNodePropertyKeyIdToValueTypeMapping = HashBasedTable.create(); + } + + public Stream calculateTabularResultStream() + { + calculateSchema(); + + // Build up a stream of SchemaInfoResult objects from calculated mappings + List results = new ArrayList<>(); + for ( LabelSet labelSet : labelSetToPropertyKeysMapping.keySet() ) + { + // lookup label names and produce list of names + List labelNames = new ArrayList<>(); + for ( int i = 0; i < labelSet.numberOfLabels(); i++ ) + { + String name = labelIdToLabelNameMapping.get( labelSet.label( i ) ); + labelNames.add( name ); + } + + Set propertyIds = labelSetToPropertyKeysMapping.get( labelSet ); + + if ( propertyIds.size() == 0 ) + { + results.add( new BuiltInSchemaProcedures.SchemaInfoResult( NODE, labelNames, null, null ) ); + } + else + { + for ( Integer propId : propertyIds ) + { + // lookup propId name and valueGroup + String propName = propertyIdToPropertylNameMapping.get( propId ); + Object valueType = labelSetAndNodePropertyKeyIdToValueTypeMapping.get( labelSet, propId ); + + String cypherType; + if ( valueType instanceof Value ) + { + cypherType = ((Value) valueType).getTypeName().toUpperCase(); + } + else if ( valueType instanceof ValueGroup ) + { + cypherType = ((ValueGroup) valueType).name(); + } + else + { + cypherType = valueType.toString(); + } + + results.add( new BuiltInSchemaProcedures.SchemaInfoResult( NODE, labelNames, propName, cypherType ) ); + } + } + } + + return results.stream(); + } + + public Stream calculateGraphResultStream() + { + calculateSchema(); + //TODO finish this + throw new NotImplementedException(); + } + + private void calculateSchema() //TODO: Parallelize this: (Nodes | Rels) and/or more + { + // this one does most of the work + //TODO: implement this for rels + try ( Statement ignore = ktx.acquireStatement() ) + { + Read dataRead = ktx.dataRead(); + TokenRead tokenRead = ktx.tokenRead(); + SchemaRead schemaRead = ktx.schemaRead(); + CursorFactory cursors = ktx.cursors(); + + // setup mappings + int labelCount = tokenRead.labelCount(); + labelSetToPropertyKeysMapping = new HashMap<>( labelCount ); + labelIdToLabelNameMapping = new HashMap<>( labelCount ); + propertyIdToPropertylNameMapping = new HashMap<>( tokenRead.propertyKeyCount() ); + + NodeCursor nodeCursor = cursors.allocateNodeCursor(); + dataRead.allNodesScan( nodeCursor ); + + while ( nodeCursor.next() ) + { + // each node + LabelSet labels = nodeCursor.labels(); + PropertyCursor propertyCursor = cursors.allocatePropertyCursor(); + nodeCursor.properties( propertyCursor ); + Set propertyIds = new HashSet<>(); // is Set really the best fit here? + + while ( propertyCursor.next() ) + { + // each property + Value currentValue = propertyCursor.propertyValue(); //1st check + int propertyKeyId = propertyCursor.propertyKey(); + + Object typeExampleValue = labelSetAndNodePropertyKeyIdToValueTypeMapping.get( labels, propertyKeyId ); + if ( typeExampleValue == null ) + { + typeExampleValue = currentValue; + } + else + { + // Object value in labelSetAndNodePropertyKeyIdToValueTypeMapping can be either: + // A) Value, if the Values match on class level + // B) ValueGroup, if the ValueGroups of the Values match + // C) String, if nothing matches + + // Are they the same value typ? -[no]-> Are they the same ValueGroup? -[no]-> AnyValue + + // TODO: We could check for String first and could skip the other instanceof checks (has Pro/Cons) + + if ( typeExampleValue instanceof Value ) + { + // check if classes match + if ( !currentValue.getClass().equals( typeExampleValue.getClass() ) ) + { + // Clases don't match -> update needed + if ( currentValue.valueGroup().equals( ((Value) typeExampleValue).valueGroup() ) ) + { + // same valueGroup -> set that + typeExampleValue = currentValue.valueGroup(); + } + else + { + // Not same valuegroup -> set to AnyValue + typeExampleValue = ANYVALUE; + } + } + } + else if ( typeExampleValue instanceof ValueGroup ) + { + if ( !currentValue.valueGroup().equals( typeExampleValue ) ) + { + // not same valueGroup -> update to AnyValue + typeExampleValue = ANYVALUE; + } + } + } + + labelSetAndNodePropertyKeyIdToValueTypeMapping.put( labels, propertyKeyId, typeExampleValue ); + propertyIds.add( propertyKeyId ); + } + + Set oldPropertyKeySet = labelSetToPropertyKeysMapping.getOrDefault( labels, emptyPropertyIdSet ); + propertyIds.addAll( oldPropertyKeySet ); + labelSetToPropertyKeysMapping.put( labels, propertyIds ); + } + + // go through all labels + Iterator labelIterator = tokenRead.labelsGetAllTokens(); + while ( labelIterator.hasNext() ) + { + NamedToken label = labelIterator.next(); + labelIdToLabelNameMapping.put( label.id(), label.name() ); + } + + // go through all propertyKeys + Iterator propIterator = tokenRead.propertyKeyGetAllTokens(); + while ( propIterator.hasNext() ) + { + NamedToken prop = propIterator.next(); + propertyIdToPropertylNameMapping.put( prop.id(), prop.name() ); + } + } + } +} 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 151a19de4710e..19d20098dfd46 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 @@ -88,4 +88,20 @@ public long[] all() { return labels; } + + @Override + public int hashCode() + { + return Arrays.hashCode( labels ); + } + + @Override + public boolean equals( Object obj ) + { + if ( obj instanceof LabelSet ) + { + return Arrays.equals( labels, ((LabelSet) obj).all() ); + } + return false; + } } diff --git a/community/kernel/src/test/java/org/neo4j/kernel/builtinprocs/BuiltInProceduresTest.java b/community/kernel/src/test/java/org/neo4j/kernel/builtinprocs/BuiltInProceduresTest.java index 16ababc16e480..231407821acab 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/builtinprocs/BuiltInProceduresTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/builtinprocs/BuiltInProceduresTest.java @@ -502,6 +502,7 @@ public void setup() throws Exception new SpecialBuiltInProcedures( "1.3.37", Edition.enterprise.toString() ).accept( procs ); procs.registerProcedure( BuiltInProcedures.class ); procs.registerProcedure( BuiltInDbmsProcedures.class ); + procs.registerProcedure( BuiltInSchemaProcedures.class ); when( tx.acquireStatement() ).thenReturn( statement ); when( tx.tokenRead() ).thenReturn( tokens ); diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/integrationtest/BuiltInSchemaProceduresIT.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/integrationtest/BuiltInSchemaProceduresIT.java new file mode 100644 index 0000000000000..8f9fab0966cc1 --- /dev/null +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/integrationtest/BuiltInSchemaProceduresIT.java @@ -0,0 +1,171 @@ +/* + * 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.impl.api.integrationtest; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import java.util.Arrays; +import java.util.Iterator; + +import org.neo4j.collection.RawIterator; +import org.neo4j.internal.kernel.api.Transaction; +import org.neo4j.internal.kernel.api.exceptions.ProcedureException; +import org.neo4j.kernel.api.ResourceTracker; +import org.neo4j.kernel.api.StubResourceManager; +import org.neo4j.kernel.api.security.AnonymousContext; +import org.neo4j.values.storable.Values; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.hamcrest.core.IsEqual.equalTo; +import static org.neo4j.helpers.collection.Iterators.asList; +import static org.neo4j.internal.kernel.api.procs.ProcedureSignature.procedureName; + +public class BuiltInSchemaProceduresIT extends KernelIntegrationTest +{ + @Rule + public ExpectedException exception = ExpectedException.none(); + + private final ResourceTracker resourceTracker = new StubResourceManager(); + + @Test + public void testSchemaTableWithNodes() throws Throwable + { + // Given + + // Node1: (:A:B {prop1:"Test", prop2:12}) + // Node2: (:B {prop1:true}) + // Node3: () + + Transaction transaction = newTransaction( AnonymousContext.writeToken() ); + long nodeId1 = transaction.dataWrite().nodeCreate(); + long nodeId2 = transaction.dataWrite().nodeCreate(); + transaction.dataWrite().nodeCreate(); // Node3 + int labelId1 = transaction.tokenWrite().labelGetOrCreateForName( "A" ); + int labelId2 = transaction.tokenWrite().labelGetOrCreateForName( "B" ); + int prop1 = transaction.tokenWrite().propertyKeyGetOrCreateForName( "prop1" ); + int prop2 = transaction.tokenWrite().propertyKeyGetOrCreateForName( "prop2" ); + transaction.dataWrite().nodeSetProperty( nodeId1, prop1, Values.stringValue("Test") ); + transaction.dataWrite().nodeSetProperty( nodeId1, prop2, Values.intValue(12) ); + transaction.dataWrite().nodeSetProperty( nodeId2, prop1, Values.booleanValue( true ) ); + transaction.dataWrite().nodeAddLabel( nodeId1, labelId1 ); + transaction.dataWrite().nodeAddLabel( nodeId1, labelId2 ); + transaction.dataWrite().nodeAddLabel( nodeId2, labelId2 ); + commit(); + + // When + RawIterator stream = + procs().procedureCallRead( procs().procedureGet( procedureName( "db", "schemaAsTable" ) ).id(), new Object[0] ); + + // Then + assertThat( asList( stream ), containsInAnyOrder( + equalTo( new Object[]{"Node", Arrays.asList( "A", "B" ), "prop1", "STRING"} ), + equalTo( new Object[]{"Node", Arrays.asList( "A", "B" ), "prop2", "INTEGER"} ), + equalTo( new Object[]{"Node", Arrays.asList( "B" ), "prop1", "BOOLEAN"} ), + equalTo( new Object[]{"Node", Arrays.asList(), null, null} )) ); + + // Just for printing out the result if needed +// printStream( stream ); + } + + @Test + public void testSchemaTableWithSimilarNodes() throws Throwable + { + // Given + + // Node1: (:A {prop1:"Test"}) + // Node2: (:A {prop1:"Test"}) + + Transaction transaction = newTransaction( AnonymousContext.writeToken() ); + long nodeId1 = transaction.dataWrite().nodeCreate(); + long nodeId2 = transaction.dataWrite().nodeCreate(); + int labelId1 = transaction.tokenWrite().labelGetOrCreateForName( "A" ); + int prop1 = transaction.tokenWrite().propertyKeyGetOrCreateForName( "prop1" ); + transaction.dataWrite().nodeSetProperty( nodeId1, prop1, Values.stringValue("Test") ); + transaction.dataWrite().nodeSetProperty( nodeId2, prop1, Values.stringValue("Test") ); + transaction.dataWrite().nodeAddLabel( nodeId1, labelId1 ); + transaction.dataWrite().nodeAddLabel( nodeId2, labelId1 ); + commit(); + + // When + RawIterator stream = + procs().procedureCallRead( procs().procedureGet( procedureName( "db", "schemaAsTable" ) ).id(), new Object[0] ); + + // Then + assertThat( asList( stream ), containsInAnyOrder( + equalTo( new Object[]{"Node", Arrays.asList("A"), "prop1", "STRING"} )) ); + + // Just for printing out the result if needed + //printStream( stream ); + } + + @Test + public void testSchemaTableWithSimilarNodesHavingDifferentPropertyValueTypes() throws Throwable + { + // Given + + // Node1: ({prop1:"Test", prop2: 12, prop3: true}) + // Node2: ({prop1:"Test", prop2: 1.5, prop3: "Test"}) + // Node3: () + + Transaction transaction = newTransaction( AnonymousContext.writeToken() ); + transaction.dataWrite().nodeCreate(); // Node3 + long nodeId1 = transaction.dataWrite().nodeCreate(); + long nodeId2 = transaction.dataWrite().nodeCreate(); + int prop1 = transaction.tokenWrite().propertyKeyGetOrCreateForName( "prop1" ); + int prop2 = transaction.tokenWrite().propertyKeyGetOrCreateForName( "prop2" ); + int prop3 = transaction.tokenWrite().propertyKeyGetOrCreateForName( "prop3" ); + transaction.dataWrite().nodeSetProperty( nodeId1, prop1, Values.stringValue("Test") ); + transaction.dataWrite().nodeSetProperty( nodeId2, prop1, Values.stringValue("Test") ); + transaction.dataWrite().nodeSetProperty( nodeId1, prop2, Values.intValue( 12 ) ); + transaction.dataWrite().nodeSetProperty( nodeId2, prop2, Values.floatValue( 1.5f ) ); + transaction.dataWrite().nodeSetProperty( nodeId1, prop3, Values.booleanValue( true ) ); + transaction.dataWrite().nodeSetProperty( nodeId2, prop3, Values.stringValue("Test") ); + commit(); + + // When + RawIterator stream = + procs().procedureCallRead( procs().procedureGet( procedureName( "db", "schemaAsTable" ) ).id(), new Object[0] ); + + // Then + assertThat( asList( stream ), containsInAnyOrder( + equalTo( new Object[]{"Node", Arrays.asList(), "prop1", "STRING"} ), + equalTo( new Object[]{"Node", Arrays.asList(), "prop2", "NUMBER"} ), + equalTo( new Object[]{"Node", Arrays.asList(), "prop3", "ANYVALUE"} ) ) ); + + // Just for printing out the result if needed + //printStream( stream ); + } + + private void printStream( RawIterator stream ) throws Throwable + { + Iterator iterator = asList( stream ).iterator(); + while ( iterator.hasNext() ) + { + Object[] row = iterator.next(); + for ( Object column : row ) + { + System.out.println( column ); + } + } + } +} diff --git a/community/values/src/main/java/org/neo4j/values/storable/BooleanArray.java b/community/values/src/main/java/org/neo4j/values/storable/BooleanArray.java index cda2c269ae20b..a389cd1465c6c 100644 --- a/community/values/src/main/java/org/neo4j/values/storable/BooleanArray.java +++ b/community/values/src/main/java/org/neo4j/values/storable/BooleanArray.java @@ -48,6 +48,12 @@ public boolean booleanValue( int offset ) return value[offset]; } + @Override + public String getTypeName() + { + return "BooleanArray"; + } + @Override public boolean equals( Value other ) { @@ -132,6 +138,6 @@ public AnyValue value( int position ) @Override public String toString() { - return format( "BooleanArray%s", Arrays.toString( value ) ); + return format( "%s%s", getTypeName(), Arrays.toString( value ) ); } } diff --git a/community/values/src/main/java/org/neo4j/values/storable/BooleanValue.java b/community/values/src/main/java/org/neo4j/values/storable/BooleanValue.java index 8132144530a4f..740c0267b94fc 100644 --- a/community/values/src/main/java/org/neo4j/values/storable/BooleanValue.java +++ b/community/values/src/main/java/org/neo4j/values/storable/BooleanValue.java @@ -66,6 +66,12 @@ public long updateHash( HashFunction hashFunction, long hash ) return hashFunction.update( hash, hashCode() ); } + @Override + public String getTypeName() + { + return "Boolean"; + } + public static final BooleanValue TRUE = new BooleanValue() { @Override @@ -120,7 +126,7 @@ public String prettyPrint() @Override public String toString() { - return format( "Boolean('%s')", Boolean.toString( true ) ); + return format( "%s('%s')", getTypeName(), Boolean.toString( true ) ); } }; @@ -178,7 +184,7 @@ public String prettyPrint() @Override public String toString() { - return format( "Boolean('%s')", Boolean.toString( false ) ); + return format( "%s('%s')", getTypeName(), Boolean.toString( false ) ); } }; } diff --git a/community/values/src/main/java/org/neo4j/values/storable/ByteArray.java b/community/values/src/main/java/org/neo4j/values/storable/ByteArray.java index aefaff3321644..e6bcd6fd54997 100644 --- a/community/values/src/main/java/org/neo4j/values/storable/ByteArray.java +++ b/community/values/src/main/java/org/neo4j/values/storable/ByteArray.java @@ -136,6 +136,12 @@ public AnyValue value( int offset ) @Override public String toString() { - return format( "ByteArray%s", Arrays.toString( value ) ); + return format( "%s%s", getTypeName(), Arrays.toString( value ) ); + } + + @Override + public String getTypeName() + { + return "ByteArray"; } } diff --git a/community/values/src/main/java/org/neo4j/values/storable/ByteValue.java b/community/values/src/main/java/org/neo4j/values/storable/ByteValue.java index b61d7e78bd531..83e40d30bf540 100644 --- a/community/values/src/main/java/org/neo4j/values/storable/ByteValue.java +++ b/community/values/src/main/java/org/neo4j/values/storable/ByteValue.java @@ -68,7 +68,7 @@ public String prettyPrint() @Override public String toString() { - return format( "Byte(%d)", value ); + return format( "%s(%d)", getTypeName(), value ); } @Override @@ -76,4 +76,10 @@ public T map( ValueMapper mapper ) { return mapper.mapByte( this ); } + + @Override + public String getTypeName() + { + return "Byte"; + } } diff --git a/community/values/src/main/java/org/neo4j/values/storable/CharArray.java b/community/values/src/main/java/org/neo4j/values/storable/CharArray.java index fa8059ce3fb62..83c0b9cbcf040 100644 --- a/community/values/src/main/java/org/neo4j/values/storable/CharArray.java +++ b/community/values/src/main/java/org/neo4j/values/storable/CharArray.java @@ -131,6 +131,12 @@ public T map( ValueMapper mapper ) @Override public String toString() { - return format( "CharArray%s", Arrays.toString( value ) ); + return format( "%s%s", getTypeName(), Arrays.toString( value ) ); + } + + @Override + public String getTypeName() + { + return "CharArray"; } } diff --git a/community/values/src/main/java/org/neo4j/values/storable/CharValue.java b/community/values/src/main/java/org/neo4j/values/storable/CharValue.java index 7b4e61b220dab..ec0873256c6c8 100644 --- a/community/values/src/main/java/org/neo4j/values/storable/CharValue.java +++ b/community/values/src/main/java/org/neo4j/values/storable/CharValue.java @@ -225,6 +225,12 @@ Matcher matcher( Pattern pattern ) @Override public String toString() { - return format( "Char('%s')", value ); + return format( "%s('%s')", getTypeName(), value ); + } + + @Override + public String getTypeName() + { + return "Char"; } } diff --git a/community/values/src/main/java/org/neo4j/values/storable/DateArray.java b/community/values/src/main/java/org/neo4j/values/storable/DateArray.java index 695428bd2cb89..8e8e9ee63d1ad 100644 --- a/community/values/src/main/java/org/neo4j/values/storable/DateArray.java +++ b/community/values/src/main/java/org/neo4j/values/storable/DateArray.java @@ -75,4 +75,10 @@ int unsafeCompareTo( Value otherValue ) { return compareToNonPrimitiveArray( (DateArray) otherValue ); } + + @Override + public String getTypeName() + { + return "DateArray"; + } } diff --git a/community/values/src/main/java/org/neo4j/values/storable/DateTimeArray.java b/community/values/src/main/java/org/neo4j/values/storable/DateTimeArray.java index ea648352c33f8..66636e27d669a 100644 --- a/community/values/src/main/java/org/neo4j/values/storable/DateTimeArray.java +++ b/community/values/src/main/java/org/neo4j/values/storable/DateTimeArray.java @@ -75,4 +75,10 @@ int unsafeCompareTo( Value otherValue ) { return compareToNonPrimitiveArray( (DateTimeArray) otherValue ); } + + @Override + public String getTypeName() + { + return "DateTimeArray"; + } } diff --git a/community/values/src/main/java/org/neo4j/values/storable/DateTimeValue.java b/community/values/src/main/java/org/neo4j/values/storable/DateTimeValue.java index da2bd22b42900..59d69a7dddc31 100644 --- a/community/values/src/main/java/org/neo4j/values/storable/DateTimeValue.java +++ b/community/values/src/main/java/org/neo4j/values/storable/DateTimeValue.java @@ -551,6 +551,12 @@ protected int computeHash() return value.toInstant().hashCode(); } + @Override + public String getTypeName() + { + return "DateTime"; + } + @Override public T map( ValueMapper mapper ) { diff --git a/community/values/src/main/java/org/neo4j/values/storable/DateValue.java b/community/values/src/main/java/org/neo4j/values/storable/DateValue.java index d18692cf6fc11..d218a83c99f2a 100644 --- a/community/values/src/main/java/org/neo4j/values/storable/DateValue.java +++ b/community/values/src/main/java/org/neo4j/values/storable/DateValue.java @@ -200,6 +200,12 @@ int unsafeCompareTo( Value otherValue ) return value.compareTo( other.value ); } + @Override + public String getTypeName() + { + return "Date"; + } + @Override LocalDate temporal() { diff --git a/community/values/src/main/java/org/neo4j/values/storable/DoubleArray.java b/community/values/src/main/java/org/neo4j/values/storable/DoubleArray.java index bec9c51d2bf0c..83d93d29fa5bd 100644 --- a/community/values/src/main/java/org/neo4j/values/storable/DoubleArray.java +++ b/community/values/src/main/java/org/neo4j/values/storable/DoubleArray.java @@ -21,7 +21,6 @@ import java.util.Arrays; -import org.neo4j.hashing.HashFunction; import org.neo4j.values.AnyValue; import org.neo4j.values.ValueMapper; @@ -137,6 +136,12 @@ public AnyValue value( int position ) @Override public String toString() { - return format( "DoubleArray%s", Arrays.toString( value ) ); + return format( "%s%s", getTypeName(), Arrays.toString( value ) ); + } + + @Override + public String getTypeName() + { + return "DoubleArray"; } } diff --git a/community/values/src/main/java/org/neo4j/values/storable/DoubleValue.java b/community/values/src/main/java/org/neo4j/values/storable/DoubleValue.java index 465a527b179f3..a3e6f5115d266 100644 --- a/community/values/src/main/java/org/neo4j/values/storable/DoubleValue.java +++ b/community/values/src/main/java/org/neo4j/values/storable/DoubleValue.java @@ -64,7 +64,7 @@ public String prettyPrint() @Override public String toString() { - return format( "Double(%e)", value ); + return format( "%s(%e)", getTypeName(), value ); } @Override @@ -72,4 +72,10 @@ public T map( ValueMapper mapper ) { return mapper.mapDouble( this ); } + + @Override + public String getTypeName() + { + return "Double"; + } } diff --git a/community/values/src/main/java/org/neo4j/values/storable/DurationArray.java b/community/values/src/main/java/org/neo4j/values/storable/DurationArray.java index 949c8073e9ec8..2e34cb9a42d26 100644 --- a/community/values/src/main/java/org/neo4j/values/storable/DurationArray.java +++ b/community/values/src/main/java/org/neo4j/values/storable/DurationArray.java @@ -86,4 +86,10 @@ int unsafeCompareTo( Value otherValue ) { return compareToNonPrimitiveArray( (DurationArray) otherValue ); } + + @Override + public String getTypeName() + { + return "DurationArray"; + } } diff --git a/community/values/src/main/java/org/neo4j/values/storable/DurationValue.java b/community/values/src/main/java/org/neo4j/values/storable/DurationValue.java index b087ca645838b..7d0d7f662d8d6 100644 --- a/community/values/src/main/java/org/neo4j/values/storable/DurationValue.java +++ b/community/values/src/main/java/org/neo4j/values/storable/DurationValue.java @@ -579,6 +579,12 @@ public String toString() return prettyPrint(); } + @Override + public String getTypeName() + { + return "Duration"; + } + @Override public String prettyPrint() { diff --git a/community/values/src/main/java/org/neo4j/values/storable/FloatArray.java b/community/values/src/main/java/org/neo4j/values/storable/FloatArray.java index aa00ee06bec16..8d839e7bd4301 100644 --- a/community/values/src/main/java/org/neo4j/values/storable/FloatArray.java +++ b/community/values/src/main/java/org/neo4j/values/storable/FloatArray.java @@ -136,6 +136,12 @@ public AnyValue value( int offset ) @Override public String toString() { - return format( "FloatArray%s", Arrays.toString( value ) ); + return format( "%s%s", getTypeName(), Arrays.toString( value ) ); + } + + @Override + public String getTypeName() + { + return "FloatArray"; } } diff --git a/community/values/src/main/java/org/neo4j/values/storable/FloatValue.java b/community/values/src/main/java/org/neo4j/values/storable/FloatValue.java index fc04649a5ab25..962bd7a0fd322 100644 --- a/community/values/src/main/java/org/neo4j/values/storable/FloatValue.java +++ b/community/values/src/main/java/org/neo4j/values/storable/FloatValue.java @@ -64,7 +64,7 @@ public String prettyPrint() @Override public String toString() { - return format( "Float(%e)", value ); + return format( "%s(%e)", getTypeName(), value ); } @Override @@ -72,4 +72,10 @@ public T map( ValueMapper mapper ) { return mapper.mapFloat( this ); } + + @Override + public String getTypeName() + { + return "Float"; + } } diff --git a/community/values/src/main/java/org/neo4j/values/storable/IntArray.java b/community/values/src/main/java/org/neo4j/values/storable/IntArray.java index d9fb75548a6dc..e3ec7b0395548 100644 --- a/community/values/src/main/java/org/neo4j/values/storable/IntArray.java +++ b/community/values/src/main/java/org/neo4j/values/storable/IntArray.java @@ -138,4 +138,10 @@ public String toString() { return format( "IntArray%s", Arrays.toString( value ) ); } + + @Override + public String getTypeName() + { + return "IntegerArray"; + } } diff --git a/community/values/src/main/java/org/neo4j/values/storable/IntValue.java b/community/values/src/main/java/org/neo4j/values/storable/IntValue.java index 3d50883599d95..8ce7e1d527213 100644 --- a/community/values/src/main/java/org/neo4j/values/storable/IntValue.java +++ b/community/values/src/main/java/org/neo4j/values/storable/IntValue.java @@ -72,4 +72,10 @@ public T map( ValueMapper mapper ) { return mapper.mapInt( this ); } + + @Override + public String getTypeName() + { + return "Integer"; + } } diff --git a/community/values/src/main/java/org/neo4j/values/storable/LocalDateTimeArray.java b/community/values/src/main/java/org/neo4j/values/storable/LocalDateTimeArray.java index 8d815a3943f39..a01036c693d0f 100644 --- a/community/values/src/main/java/org/neo4j/values/storable/LocalDateTimeArray.java +++ b/community/values/src/main/java/org/neo4j/values/storable/LocalDateTimeArray.java @@ -75,4 +75,10 @@ int unsafeCompareTo( Value otherValue ) { return compareToNonPrimitiveArray( (LocalDateTimeArray) otherValue ); } + + @Override + public String getTypeName() + { + return "LocalDateTimeArray"; + } } diff --git a/community/values/src/main/java/org/neo4j/values/storable/LocalDateTimeValue.java b/community/values/src/main/java/org/neo4j/values/storable/LocalDateTimeValue.java index f3a7b9503999e..9a383ddf4fc70 100644 --- a/community/values/src/main/java/org/neo4j/values/storable/LocalDateTimeValue.java +++ b/community/values/src/main/java/org/neo4j/values/storable/LocalDateTimeValue.java @@ -286,6 +286,12 @@ int unsafeCompareTo( Value other ) return cmp; } + @Override + public String getTypeName() + { + return "LocalDateTime"; + } + @Override LocalDateTime temporal() { diff --git a/community/values/src/main/java/org/neo4j/values/storable/LocalTimeArray.java b/community/values/src/main/java/org/neo4j/values/storable/LocalTimeArray.java index cf796b25b5ea3..a972f8afd4d78 100644 --- a/community/values/src/main/java/org/neo4j/values/storable/LocalTimeArray.java +++ b/community/values/src/main/java/org/neo4j/values/storable/LocalTimeArray.java @@ -75,4 +75,10 @@ int unsafeCompareTo( Value otherValue ) { return compareToNonPrimitiveArray( (LocalTimeArray) otherValue ); } + + @Override + public String getTypeName() + { + return "LocalTimeArray"; + } } diff --git a/community/values/src/main/java/org/neo4j/values/storable/LocalTimeValue.java b/community/values/src/main/java/org/neo4j/values/storable/LocalTimeValue.java index 24f72c541ecf4..337f5b8bd96f4 100644 --- a/community/values/src/main/java/org/neo4j/values/storable/LocalTimeValue.java +++ b/community/values/src/main/java/org/neo4j/values/storable/LocalTimeValue.java @@ -197,6 +197,12 @@ LocalTime temporal() return value; } + @Override + public String getTypeName() + { + return "LocalTime"; + } + @Override LocalDate getDatePart() { diff --git a/community/values/src/main/java/org/neo4j/values/storable/LongArray.java b/community/values/src/main/java/org/neo4j/values/storable/LongArray.java index 7db36d39aac21..3cceea4de26ed 100644 --- a/community/values/src/main/java/org/neo4j/values/storable/LongArray.java +++ b/community/values/src/main/java/org/neo4j/values/storable/LongArray.java @@ -136,6 +136,12 @@ public AnyValue value( int offset ) @Override public String toString() { - return format( "LongArray%s", Arrays.toString( value ) ); + return format( "%s%s", getTypeName(), Arrays.toString( value ) ); + } + + @Override + public String getTypeName() + { + return "LongArray"; } } diff --git a/community/values/src/main/java/org/neo4j/values/storable/LongValue.java b/community/values/src/main/java/org/neo4j/values/storable/LongValue.java index 378743c597dbf..b0b046cb2b172 100644 --- a/community/values/src/main/java/org/neo4j/values/storable/LongValue.java +++ b/community/values/src/main/java/org/neo4j/values/storable/LongValue.java @@ -64,7 +64,7 @@ public String prettyPrint() @Override public String toString() { - return format( "Long(%d)", value ); + return format( "%s(%d)", getTypeName(), value ); } @Override @@ -72,4 +72,10 @@ public T map( ValueMapper mapper ) { return mapper.mapLong( this ); } + + @Override + public String getTypeName() + { + return "Long"; + } } diff --git a/community/values/src/main/java/org/neo4j/values/storable/NoValue.java b/community/values/src/main/java/org/neo4j/values/storable/NoValue.java index 225c0fd000f2c..6b54af852ac04 100644 --- a/community/values/src/main/java/org/neo4j/values/storable/NoValue.java +++ b/community/values/src/main/java/org/neo4j/values/storable/NoValue.java @@ -94,6 +94,12 @@ public String toString() @Override public String prettyPrint() + { + return getTypeName(); + } + + @Override + public String getTypeName() { return "NO_VALUE"; } diff --git a/community/values/src/main/java/org/neo4j/values/storable/PointArray.java b/community/values/src/main/java/org/neo4j/values/storable/PointArray.java index 19aed0528979b..1a1202064c0ac 100644 --- a/community/values/src/main/java/org/neo4j/values/storable/PointArray.java +++ b/community/values/src/main/java/org/neo4j/values/storable/PointArray.java @@ -87,4 +87,10 @@ int unsafeCompareTo( Value otherValue ) { return compareToNonPrimitiveArray( (PointArray) otherValue ); } + + @Override + public String getTypeName() + { + return "PointArray"; + } } 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 994d876c9eb8b..b234968e4b5ef 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 @@ -234,7 +234,13 @@ 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( "point({%s, crs: '%s'})", coordString, getCoordinateReferenceSystem().getName() ); + return format( "%s({%s, crs: '%s'})", getTypeName(), coordString, getCoordinateReferenceSystem().getName() ); + } + + @Override + public String getTypeName() + { + return "Point"; } /** diff --git a/community/values/src/main/java/org/neo4j/values/storable/ShortArray.java b/community/values/src/main/java/org/neo4j/values/storable/ShortArray.java index 7c86b8c6f6f27..3352840931783 100644 --- a/community/values/src/main/java/org/neo4j/values/storable/ShortArray.java +++ b/community/values/src/main/java/org/neo4j/values/storable/ShortArray.java @@ -136,6 +136,12 @@ public AnyValue value( int offset ) @Override public String toString() { - return format( "ShortArray%s", Arrays.toString( value ) ); + return format( "%s%s", getTypeName(), Arrays.toString( value ) ); + } + + @Override + public String getTypeName() + { + return "ShortArray"; } } diff --git a/community/values/src/main/java/org/neo4j/values/storable/ShortValue.java b/community/values/src/main/java/org/neo4j/values/storable/ShortValue.java index 0dfddf343075c..67f45fd1cae9a 100644 --- a/community/values/src/main/java/org/neo4j/values/storable/ShortValue.java +++ b/community/values/src/main/java/org/neo4j/values/storable/ShortValue.java @@ -68,7 +68,7 @@ public String prettyPrint() @Override public String toString() { - return format( "Short(%d)", value ); + return format( "%s(%d)", getTypeName(), value ); } @Override @@ -76,4 +76,10 @@ public T map( ValueMapper mapper ) { return mapper.mapShort( this ); } + + @Override + public String getTypeName() + { + return "Short"; + } } diff --git a/community/values/src/main/java/org/neo4j/values/storable/StringArray.java b/community/values/src/main/java/org/neo4j/values/storable/StringArray.java index 2bcb2d6ed63e8..87cf227a0bb88 100644 --- a/community/values/src/main/java/org/neo4j/values/storable/StringArray.java +++ b/community/values/src/main/java/org/neo4j/values/storable/StringArray.java @@ -124,6 +124,12 @@ public T map( ValueMapper mapper ) @Override public String toString() { - return format( "StringArray%s", Arrays.toString( value ) ); + return format( "%s%s", getTypeName(), Arrays.toString( value ) ); + } + + @Override + public String getTypeName() + { + return "StringArray"; } } diff --git a/community/values/src/main/java/org/neo4j/values/storable/StringValue.java b/community/values/src/main/java/org/neo4j/values/storable/StringValue.java index 34f4aa7addfe1..7ced36b626765 100644 --- a/community/values/src/main/java/org/neo4j/values/storable/StringValue.java +++ b/community/values/src/main/java/org/neo4j/values/storable/StringValue.java @@ -141,7 +141,13 @@ public Object asObjectCopy() @Override public String toString() { - return format( "String(\"%s\")", value() ); + return format( "%s(\"%s\")", getTypeName(), value() ); + } + + @Override + public String getTypeName() + { + return "String"; } @Override diff --git a/community/values/src/main/java/org/neo4j/values/storable/TimeArray.java b/community/values/src/main/java/org/neo4j/values/storable/TimeArray.java index b5c39b6b3098d..a7302329151df 100644 --- a/community/values/src/main/java/org/neo4j/values/storable/TimeArray.java +++ b/community/values/src/main/java/org/neo4j/values/storable/TimeArray.java @@ -75,4 +75,10 @@ int unsafeCompareTo( Value otherValue ) { return compareToNonPrimitiveArray( (TimeArray) otherValue ); } + + @Override + public String getTypeName() + { + return "TimeArray"; + } } diff --git a/community/values/src/main/java/org/neo4j/values/storable/TimeValue.java b/community/values/src/main/java/org/neo4j/values/storable/TimeValue.java index e6b30ae008a71..2309a3e246883 100644 --- a/community/values/src/main/java/org/neo4j/values/storable/TimeValue.java +++ b/community/values/src/main/java/org/neo4j/values/storable/TimeValue.java @@ -76,6 +76,12 @@ public static TimeValue time( long nanosOfDayUTC, ZoneOffset offset ) return new TimeValue( OffsetTime.ofInstant( assertValidArgument( () -> Instant.ofEpochSecond( 0, nanosOfDayUTC ) ), offset ) ); } + @Override + public String getTypeName() + { + return "Time"; + } + public static TimeValue parse( CharSequence text, Supplier defaultZone, CSVHeaderInformation fieldsFromHeader ) { if ( fieldsFromHeader != null ) diff --git a/community/values/src/main/java/org/neo4j/values/storable/Value.java b/community/values/src/main/java/org/neo4j/values/storable/Value.java index f396fffa605cb..1ea87530238d1 100644 --- a/community/values/src/main/java/org/neo4j/values/storable/Value.java +++ b/community/values/src/main/java/org/neo4j/values/storable/Value.java @@ -279,4 +279,6 @@ static void parseHeaderInformation( CharSequence text, String type, CSVHeaderInf } while ( matcher.find() ); } + + public abstract String getTypeName(); }