Skip to content

Commit

Permalink
equality of OrderedPropertyValues
Browse files Browse the repository at this point in the history
  • Loading branch information
fickludd committed Mar 8, 2017
1 parent b668cf4 commit 796a19e
Show file tree
Hide file tree
Showing 27 changed files with 122 additions and 78 deletions.
Expand Up @@ -40,7 +40,7 @@ public class IndexEntryConflictException extends Exception


public IndexEntryConflictException( long existingNodeId, long addedNodeId, Object propertyValue ) public IndexEntryConflictException( long existingNodeId, long addedNodeId, Object propertyValue )
{ {
this( existingNodeId, addedNodeId, OrderedPropertyValues.of( propertyValue ) ); this( existingNodeId, addedNodeId, OrderedPropertyValues.ofUndefined( propertyValue ) );
} }


public IndexEntryConflictException( long existingNodeId, long addedNodeId, OrderedPropertyValues propertyValues ) public IndexEntryConflictException( long existingNodeId, long addedNodeId, OrderedPropertyValues propertyValues )
Expand Down Expand Up @@ -150,7 +150,7 @@ private String propertyString( TokenNameLookup tokenNameLookup, int[] propertyId
sb.append( '`' ); sb.append( '`' );
sb.append( tokenNameLookup.propertyKeyGetName( propertyIds[i] ) ); sb.append( tokenNameLookup.propertyKeyGetName( propertyIds[i] ) );
sb.append( "` = " ); sb.append( "` = " );
sb.append( OrderedPropertyValues.quote( propertyValues.values()[i] ) ); sb.append( OrderedPropertyValues.quote( propertyValues.valueAt( i ) ) );
} }
return sb.toString(); return sb.toString();
} }
Expand Down
Expand Up @@ -71,7 +71,7 @@ static boolean valueEquals( boolean[] value, Object other )
} }


@Override @Override
int valueHash() public int valueHash()
{ {
return hash( value ); return hash( value );
} }
Expand Down
Expand Up @@ -47,7 +47,7 @@ public Boolean value()
} }


@Override @Override
int valueHash() public int valueHash()
{ {
return value ? -1 : 0; return value ? -1 : 0;
} }
Expand Down
Expand Up @@ -75,7 +75,7 @@ else if ( other instanceof String[] )
} }


@Override @Override
int valueHash() public int valueHash()
{ {
return hash( value ); return hash( value );
} }
Expand Down
Expand Up @@ -56,7 +56,7 @@ public Character value()
} }


@Override @Override
int valueHash() public int valueHash()
{ {
return value; return value;
} }
Expand Down
Expand Up @@ -57,7 +57,7 @@ public Object value()
} }


@Override @Override
int valueHash() public int valueHash()
{ {
return -1; return -1;
} }
Expand Down Expand Up @@ -143,7 +143,7 @@ public final int hashCode()
return propertyKeyId ^ valueHash(); return propertyKeyId ^ valueHash();
} }


abstract int valueHash(); public abstract int valueHash();


/** We never pass {@link LazyProperty} to this method, since we check for it in {@link #equals(Object)}. */ /** We never pass {@link LazyProperty} to this method, since we check for it in {@link #equals(Object)}. */
abstract boolean hasEqualValue( DefinedProperty that ); abstract boolean hasEqualValue( DefinedProperty that );
Expand Down
Expand Up @@ -31,7 +31,7 @@ abstract class FloatingPointArrayProperty extends DefinedProperty implements Arr
public abstract double doubleValue( int index ); public abstract double doubleValue( int index );


@Override @Override
final int valueHash() public final int valueHash()
{ {
return hash( this ); return hash( this );
} }
Expand Down
Expand Up @@ -29,7 +29,7 @@ abstract class FloatingPointNumberProperty extends NumberProperty
} }


@Override @Override
final int valueHash() public final int valueHash()
{ {
long value = (long) doubleValue(); long value = (long) doubleValue();
return (int) (value ^ (value >>> 32)); return (int) (value ^ (value >>> 32));
Expand Down
Expand Up @@ -31,7 +31,7 @@ abstract class IntegralArrayProperty extends DefinedProperty implements ArrayVal
public abstract long longValue( int index ); public abstract long longValue( int index );


@Override @Override
final int valueHash() public final int valueHash()
{ {
return hash( this ); return hash( this );
} }
Expand Down
Expand Up @@ -33,7 +33,7 @@ public double doubleValue()
} }


@Override @Override
final int valueHash() public final int valueHash()
{ {
long value = longValue(); long value = longValue();
return (int) (value ^ (value >>> 32)); return (int) (value ^ (value >>> 32));
Expand Down
Expand Up @@ -59,7 +59,7 @@ public boolean valueEquals( Object value )
} }


@Override @Override
int valueHash() public int valueHash()
{ {
Object myValue = value(); // value() accesses LazyProperty.value, implying a read barrier ... Object myValue = value(); // value() accesses LazyProperty.value, implying a read barrier ...
return type.hashCode( myValue ); // ... so accessing type is safe return type.hashCode( myValue ); // ... so accessing type is safe
Expand Down
Expand Up @@ -35,7 +35,7 @@ public boolean valueEquals( Object value )
} }


@Override @Override
int valueHash() public int valueHash()
{ {
return value().hashCode(); return value().hashCode();
} }
Expand Down
Expand Up @@ -77,7 +77,7 @@ else if ( other instanceof Character[] )
} }


@Override @Override
int valueHash() public int valueHash()
{ {
return hash( value ); return hash( value );
} }
Expand Down
Expand Up @@ -57,7 +57,7 @@ public String value()
} }


@Override @Override
int valueHash() public int valueHash()
{ {
return value.hashCode(); return value.hashCode();
} }
Expand Down
Expand Up @@ -22,45 +22,62 @@
import java.util.Arrays; import java.util.Arrays;
import java.util.Comparator; import java.util.Comparator;


import org.neo4j.kernel.api.properties.DefinedProperty;
import org.neo4j.kernel.api.properties.Property;

import static org.neo4j.kernel.api.StatementConstants.NO_SUCH_PROPERTY_KEY;
import static org.neo4j.kernel.impl.api.PropertyValueComparison.COMPARE_VALUES; import static org.neo4j.kernel.impl.api.PropertyValueComparison.COMPARE_VALUES;


import static java.lang.String.format; import static java.lang.String.format;
import static java.lang.String.valueOf; import static java.lang.String.valueOf;


/** /**
* Holder for n property values, ordered according to a schema descriptor property id order * Holder for n property values, ordered according to a schema descriptor property id order
*
* This implementation uses the Property class hierarchy to achieve correct equality between property values of
* different types. However, the propertyKeyId is really not needed and we could consider reimplementing the class if
* we make static methods for comparing property values.
*/ */
public class OrderedPropertyValues public class OrderedPropertyValues
{ {
// FACTORY METHODS // FACTORY METHODS


public static OrderedPropertyValues of( Object... values ) public static OrderedPropertyValues ofUndefined( Object... values )
{
return new OrderedPropertyValues(
Arrays.stream( values )
.map( value -> Property.property( NO_SUCH_PROPERTY_KEY, value ) )
.toArray( DefinedProperty[]::new )
);
}

public static OrderedPropertyValues of( DefinedProperty[] values )
{ {
return new OrderedPropertyValues( values ); return new OrderedPropertyValues( values );
} }


public static OrderedPropertyValues of( IndexQuery.ExactPredicate[] exactPreds ) public static OrderedPropertyValues of( IndexQuery.ExactPredicate[] exactPreds )
{ {
Object[] values = new Object[exactPreds.length]; DefinedProperty[] values = new DefinedProperty[exactPreds.length];
for ( int i = 0; i < exactPreds.length; i++ ) for ( int i = 0; i < exactPreds.length; i++ )
{ {
values[i] = exactPreds[i].value(); values[i] = Property.property( exactPreds[i].propertyKeyId(), exactPreds[i].value() );
} }
return new OrderedPropertyValues( values ); return new OrderedPropertyValues( values );
} }


// ACTUAL CLASS // ACTUAL CLASS


private final Object[] values; private final DefinedProperty[] properties;


private OrderedPropertyValues( Object[] values ) private OrderedPropertyValues( DefinedProperty[] properties )
{ {
this.values = values; this.properties = properties;
} }


public Object[] values() public Object valueAt( int position )
{ {
return values; return properties[position].value();
} }


@Override @Override
Expand All @@ -77,36 +94,53 @@ public boolean equals( Object o )


OrderedPropertyValues that = (OrderedPropertyValues) o; OrderedPropertyValues that = (OrderedPropertyValues) o;


return Arrays.deepEquals( values, that.values ); if ( that.properties.length != properties.length )
{
return false;
}

for ( int i = 0; i < properties.length; i++ )
{
if ( !properties[i].valueEquals( that.properties[i].value() ) )
{
return false;
}
}
return true;
} }


@Override @Override
public int hashCode() public int hashCode()
{ {
return Arrays.deepHashCode( values ); int result = 0;
for ( DefinedProperty property : properties )
{
result = 31 * ( result + property.valueHash() );
}
return result;
} }


public int size() public int size()
{ {
return values.length; return properties.length;
} }


public Object getSinglePropertyValue() public Object getSinglePropertyValue()
{ {
assert values.length == 1 : "Assumed single property but had " + values.length; assert properties.length == 1 : "Assumed single property but had " + properties.length;
return values[0]; return properties[0].value();
} }


@Override @Override
public String toString() public String toString()
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
String sep = "( "; String sep = "( ";
for ( Object value : values ) for ( DefinedProperty property : properties )
{ {
sb.append( sep ); sb.append( sep );
sep = ", "; sep = ", ";
sb.append( quote( value ) ); sb.append( quote( property.value() ) );
} }
sb.append( " )" ); sb.append( " )" );
return sb.toString(); return sb.toString();
Expand Down Expand Up @@ -155,15 +189,15 @@ else if ( propertyValue.getClass().isArray() )


public static final Comparator<OrderedPropertyValues> COMPARATOR = ( left, right ) -> public static final Comparator<OrderedPropertyValues> COMPARATOR = ( left, right ) ->
{ {
if ( left.values.length != right.values.length ) if ( left.properties.length != right.properties.length )
{ {
throw new IllegalStateException( "Comparing two OrderedPropertyValues of different lengths!" ); throw new IllegalStateException( "Comparing two OrderedPropertyValues of different lengths!" );
} }


int compare = 0; int compare = 0;
for ( int i = 0; i < left.values.length; i++ ) for ( int i = 0; i < left.properties.length; i++ )
{ {
compare = COMPARE_VALUES.compare( left.values[i], right.values[i] ); compare = COMPARE_VALUES.compare( left.properties[i].value(), right.properties[i].value() );
if ( compare != 0 ) if ( compare != 0 )
{ {
return compare; return compare;
Expand Down
Expand Up @@ -63,6 +63,11 @@ public static PrimitiveLongIterator exactIndexMatches( PropertyAccessor accessor
public static PrimitiveLongIterator exactIndexMatches( EntityOperations operations, KernelStatement state, public static PrimitiveLongIterator exactIndexMatches( EntityOperations operations, KernelStatement state,
PrimitiveLongIterator indexedNodeIds, IndexQuery... predicates ) PrimitiveLongIterator indexedNodeIds, IndexQuery... predicates )
{ {
if ( !indexedNodeIds.hasNext() )
{
return indexedNodeIds;
}

IndexQuery[] numericPredicates = IndexQuery[] numericPredicates =
Arrays.stream( predicates ) Arrays.stream( predicates )
.filter( LookupFilter::isNumericPredicate ) .filter( LookupFilter::isNumericPredicate )
Expand Down
Expand Up @@ -24,9 +24,9 @@
import org.neo4j.collection.primitive.Primitive; import org.neo4j.collection.primitive.Primitive;
import org.neo4j.collection.primitive.PrimitiveIntSet; import org.neo4j.collection.primitive.PrimitiveIntSet;
import org.neo4j.helpers.collection.Iterators; import org.neo4j.helpers.collection.Iterators;
import org.neo4j.kernel.api.ReadOperations;
import org.neo4j.kernel.api.exceptions.EntityNotFoundException; import org.neo4j.kernel.api.exceptions.EntityNotFoundException;
import org.neo4j.kernel.api.properties.DefinedProperty; import org.neo4j.kernel.api.properties.DefinedProperty;
import org.neo4j.kernel.api.properties.Property;
import org.neo4j.kernel.api.schema_new.LabelSchemaDescriptor; import org.neo4j.kernel.api.schema_new.LabelSchemaDescriptor;
import org.neo4j.kernel.api.schema_new.OrderedPropertyValues; import org.neo4j.kernel.api.schema_new.OrderedPropertyValues;
import org.neo4j.kernel.api.schema_new.index.NewIndexDescriptor; import org.neo4j.kernel.api.schema_new.index.NewIndexDescriptor;
Expand Down Expand Up @@ -171,7 +171,7 @@ public void updateIndexIfApplicable( KernelStatement state, NodeItem node,
} }
} }
state.txState().indexDoUpdateEntry( index.schema(), node.id(), state.txState().indexDoUpdateEntry( index.schema(), node.id(),
OrderedPropertyValues.of( valuesBefore ), OrderedPropertyValues.of( valuesAfter ) ); OrderedPropertyValues.ofUndefined( valuesBefore ), OrderedPropertyValues.ofUndefined( valuesAfter ) );
} }
} }


Expand Down Expand Up @@ -211,8 +211,7 @@ private OrderedPropertyValues valuesIfPropertiesMatch( KernelStatement state, Pr
return valuesIfPropertiesMatch( state, nodeProperties, index, node, NO_SUCH_PROPERTY ); return valuesIfPropertiesMatch( state, nodeProperties, index, node, NO_SUCH_PROPERTY );
} }


private OrderedPropertyValues valuesIfPropertiesMatch( KernelStatement state, PrimitiveIntSet private OrderedPropertyValues valuesIfPropertiesMatch( KernelStatement state, PrimitiveIntSet nodeProperties,
nodeProperties,
NewIndexDescriptor index, NodeItem node, DefinedProperty changedProperty ) throws EntityNotFoundException NewIndexDescriptor index, NodeItem node, DefinedProperty changedProperty ) throws EntityNotFoundException
{ {
int[] indexPropertyIds = index.schema().getPropertyIds(); int[] indexPropertyIds = index.schema().getPropertyIds();
Expand All @@ -221,12 +220,13 @@ private OrderedPropertyValues valuesIfPropertiesMatch( KernelStatement state, Pr
return null; return null;
} }


Object[] values = new Object[indexPropertyIds.length]; DefinedProperty[] values = new DefinedProperty[indexPropertyIds.length];
for ( int i = 0; i < values.length; i++ ) for ( int i = 0; i < values.length; i++ )
{ {
int indexPropertyId = indexPropertyIds[i]; int indexPropertyId = indexPropertyIds[i];
values[i] = indexPropertyId == changedProperty.propertyKeyId() ? values[i] = indexPropertyId == changedProperty.propertyKeyId()
changedProperty.value() : readOps.nodeGetProperty( state, node, indexPropertyId ); ? changedProperty
: Property.property( indexPropertyId, readOps.nodeGetProperty( state, node, indexPropertyId ) );
} }


return OrderedPropertyValues.of( values ); return OrderedPropertyValues.of( values );
Expand Down

0 comments on commit 796a19e

Please sign in to comment.