Skip to content

Commit

Permalink
add orderability support for Nodes, Relationships, and Paths
Browse files Browse the repository at this point in the history
- fix cases where orderability of Lists failed: Integer[], Long[], Float[], Double, float[], double[]
  • Loading branch information
alexaverbuch committed Feb 14, 2017
1 parent 6448b53 commit ea9e5f9
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 29 deletions.
Expand Up @@ -24,11 +24,14 @@
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.stream.DoubleStream;
import java.util.stream.IntStream; import java.util.stream.IntStream;
import java.util.stream.LongStream;


import org.neo4j.cypher.UnorderableValueException; import org.neo4j.cypher.UnorderableValueException;
import org.neo4j.cypher.internal.frontend.v3_2.IncomparableValuesException; import org.neo4j.cypher.internal.frontend.v3_2.IncomparableValuesException;
import org.neo4j.graphdb.Path; import org.neo4j.graphdb.Path;
import org.neo4j.graphdb.PropertyContainer;
import org.neo4j.helpers.MathUtil; import org.neo4j.helpers.MathUtil;


import static java.lang.String.format; import static java.lang.String.format;
Expand Down Expand Up @@ -124,10 +127,10 @@ else if ( rhs == null )
public enum SuperType public enum SuperType
{ {
MAP( 0, FALLBACK_COMPARATOR /*TODO*/ ), MAP( 0, FALLBACK_COMPARATOR /*TODO*/ ),
NODE( 1, FALLBACK_COMPARATOR /*TODO*/ ), NODE( 1, NODE_COMPARATOR ),
RELATIONSHIP( 2, FALLBACK_COMPARATOR /*TODO*/ ), RELATIONSHIP( 2, RELATIONSHIP_COMPARATOR ),
LIST( 3, LIST_COMPARATOR ), LIST( 3, LIST_COMPARATOR ),
PATH( 4, FALLBACK_COMPARATOR /*TODO*/ ), PATH( 4, PATH_COMPARATOR ),
STRING( 5, STRING_COMPARATOR ), STRING( 5, STRING_COMPARATOR ),
BOOLEAN( 6, BOOLEAN_COMPARATOR ), BOOLEAN( 6, BOOLEAN_COMPARATOR ),
NUMBER( 7, NUMBER_COMPARATOR ), NUMBER( 7, NUMBER_COMPARATOR ),
Expand Down Expand Up @@ -185,6 +188,7 @@ else if ( value instanceof RelationshipIdWrapper )
} }
return RELATIONSHIP; return RELATIONSHIP;
} }
// TODO is Path really the class that compiled runtime will be using?
else if ( value instanceof Path ) else if ( value instanceof Path )
{ {
return PATH; return PATH;
Expand All @@ -205,7 +209,7 @@ public int compare( SuperType left, SuperType right )
// NOTE: nulls are handled at the top of the public compare() method // NOTE: nulls are handled at the top of the public compare() method
// so the type-specific comparators should not check arguments for null // so the type-specific comparators should not check arguments for null


private static Comparator FALLBACK_COMPARATOR = new Comparator<Object>() private static Comparator<Object> FALLBACK_COMPARATOR = new Comparator<Object>()
{ {
@Override @Override
public int compare( Object lhs, Object rhs ) public int compare( Object lhs, Object rhs )
Expand All @@ -221,7 +225,7 @@ public int compare( Object lhs, Object rhs )
} }
}; };


private static Comparator VOID_COMPARATOR = new Comparator<Object>() private static Comparator<Object> VOID_COMPARATOR = new Comparator<Object>()
{ {
@Override @Override
public int compare( Object lhs, Object rhs ) public int compare( Object lhs, Object rhs )
Expand All @@ -230,7 +234,7 @@ public int compare( Object lhs, Object rhs )
} }
}; };


private static Comparator NUMBER_COMPARATOR = new Comparator<Number>() private static Comparator<Number> NUMBER_COMPARATOR = new Comparator<Number>()
{ {
@Override @Override
public int compare( Number lhs, Number rhs ) public int compare( Number lhs, Number rhs )
Expand Down Expand Up @@ -267,7 +271,7 @@ else if ( (rhs instanceof Double || rhs instanceof Float) )
} }
}; };


private static Comparator STRING_COMPARATOR = new Comparator<Object>() private static Comparator<Object> STRING_COMPARATOR = new Comparator<Object>()
{ {
@Override @Override
public int compare( Object lhs, Object rhs ) public int compare( Object lhs, Object rhs )
Expand All @@ -285,7 +289,7 @@ else if ( lhs instanceof String && rhs instanceof Character )
} }
}; };


private static Comparator BOOLEAN_COMPARATOR = new Comparator<Boolean>() private static Comparator<Boolean> BOOLEAN_COMPARATOR = new Comparator<Boolean>()
{ {
@Override @Override
public int compare( Boolean lhs, Boolean rhs ) public int compare( Boolean lhs, Boolean rhs )
Expand All @@ -294,13 +298,53 @@ public int compare( Boolean lhs, Boolean rhs )
} }
}; };


private static Comparator LIST_COMPARATOR = new Comparator<Object>() private static Comparator<NodeIdWrapper> NODE_COMPARATOR = new Comparator<NodeIdWrapper>()
{
@Override
public int compare( NodeIdWrapper lhs, NodeIdWrapper rhs )
{
return Long.compare( lhs.id(), rhs.id() );
}
};

private static Comparator<RelationshipIdWrapper> RELATIONSHIP_COMPARATOR = new Comparator<RelationshipIdWrapper>()
{
@Override
public int compare( RelationshipIdWrapper lhs, RelationshipIdWrapper rhs )
{
return Long.compare( lhs.id(), rhs.id() );
}
};

// TODO test
private static Comparator<Path> PATH_COMPARATOR = new Comparator<Path>()
{
@Override
public int compare( Path lhs, Path rhs )
{
Iterator<PropertyContainer> lhsIter = lhs.iterator();
Iterator<PropertyContainer> rhsIter = lhs.iterator();
while ( lhsIter.hasNext() && rhsIter.hasNext() )
{
int result = CompiledOrderabilityUtils.compare( lhsIter.next(), rhsIter.next() );
if ( 0 != result )
{
return result;
}
}
return (lhsIter.hasNext()) ? 1
: (rhsIter.hasNext()) ? -1
: 0;
}
};

private static Comparator<Object> LIST_COMPARATOR = new Comparator<Object>()
{ {
@Override @Override
public int compare( Object lhs, Object rhs ) public int compare( Object lhs, Object rhs )
{ {
Iterator lhsIter = (lhs.getClass().isArray()) ? arrayToIterator( lhs ) : ((List) lhs).iterator(); Iterator lhsIter = toIterator( lhs );
Iterator rhsIter = (rhs.getClass().isArray()) ? arrayToIterator( rhs ) : ((List) rhs).iterator(); Iterator rhsIter = toIterator( rhs );
while ( lhsIter.hasNext() && rhsIter.hasNext() ) while ( lhsIter.hasNext() && rhsIter.hasNext() )
{ {
int result = CompiledOrderabilityUtils.compare( lhsIter.next(), rhsIter.next() ); int result = CompiledOrderabilityUtils.compare( lhsIter.next(), rhsIter.next() );
Expand All @@ -314,28 +358,32 @@ public int compare( Object lhs, Object rhs )
: 0; : 0;
} }


private Iterator arrayToIterator( Object o ) private Iterator toIterator( Object o )
{ {
Class clazz = o.getClass(); Class clazz = o.getClass();
if ( clazz.equals( Object[].class ) ) if ( Iterable.class.isAssignableFrom( clazz) )
{
return ((Iterable) o).iterator();
}
else if ( Object[].class.isAssignableFrom( clazz) )
{ {
return Arrays.stream( (Object[]) o ).iterator(); return Arrays.stream( (Object[]) o ).iterator();
} }
else if ( clazz.equals( int[].class ) ) else if ( clazz.equals( int[].class ) )
{ {
return Arrays.stream( (int[]) o ).iterator(); return IntStream.of( (int[]) o ).iterator();
} }
else if ( clazz.equals( Integer[].class ) ) else if ( clazz.equals( long[].class ) )
{ {
return Arrays.stream( (Integer[]) o ).iterator(); return LongStream.of( (long[]) o ).iterator();
} }
else if ( clazz.equals( long[].class ) ) else if ( clazz.equals( float[].class ) )
{ {
return Arrays.stream( (long[]) o ).iterator(); return IntStream.range( 0, ((float[]) o).length ).mapToObj( i -> ((float[]) o)[i] ).iterator();
} }
else if ( clazz.equals( Long[].class ) ) else if ( clazz.equals( double[].class ) )
{ {
return Arrays.stream( (Long[]) o ).iterator(); return DoubleStream.of( (double[]) o ).iterator();
} }
else if ( clazz.equals( String[].class ) ) else if ( clazz.equals( String[].class ) )
{ {
Expand Down
Expand Up @@ -44,26 +44,35 @@ public class CompiledOrderabilityUtilsTest


// NODE // NODE
new NodeIdWrapper( 1 ), new NodeIdWrapper( 1 ),
//new NodeIdWrapper( 2 ), TODO: FIXME new NodeIdWrapper( 2 ),


// RELATIONSHIP // RELATIONSHIP
new RelationshipIdWrapper( 1 ), new RelationshipIdWrapper( 1 ),
//new RelationshipIdWrapper( 2 ), TODO: FIXME new RelationshipIdWrapper( 2 ),


// LIST // LIST
new String[]{"boo"},
new String[]{"foo"}, new String[]{"foo"},
new boolean[]{false},
new Boolean[]{true},
new Object[]{1, "foo"}, new Object[]{1, "foo"},
new Object[]{1, "foo", 3}, new Object[]{1, "foo", 3},
new Object[]{1, true, "car"}, new Object[]{1, true, "car"},
new Object[]{1, 2, "bar"}, new Object[]{1, 2, "bar"},
new Object[]{1, 2, "car"}, new Object[]{1, 2, "car"},
new int[] {1, 2, 3}, new int[]{1, 2, 3},
new Object[]{1, 2, 3L, Double.NEGATIVE_INFINITY}, new Object[]{1, 2, 3L, Double.NEGATIVE_INFINITY},
new long[] {1, 2, 3, Long.MIN_VALUE}, new long[]{1, 2, 3, Long.MIN_VALUE},
new int[] {1, 2, 3, Integer.MIN_VALUE}, new int[]{1, 2, 3, Integer.MIN_VALUE},
new Object[]{1L, 2, 3, Double.NaN}, new Object[]{1L, 2, 3, Double.NaN},
new Object[]{1L, 2, 3, new NodeIdWrapper(-1)}, new Object[]{1L, 2, 3, new NodeIdWrapper(-1)},
new int[] {2}, new Long[]{1L, 2L, 4L},
new int[]{2},
new Integer[]{3},
new double[]{4D},
new Double[]{5D},
new float[]{6},
new Float[]{7F},
new Object[]{new RelationshipIdWrapper(-1)}, new Object[]{new RelationshipIdWrapper(-1)},


// TODO: PATH // TODO: PATH
Expand Down

0 comments on commit ea9e5f9

Please sign in to comment.