org.neo4j.kernel.impl.index.schema.CompositeRangeKey Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of neo4j-kernel Show documentation
Show all versions of neo4j-kernel Show documentation
Neo4j kernel is a lightweight, embedded Java database designed to
store data structured as graphs rather than tables. For more
information, see http://neo4j.org.
/*
* Copyright (c) "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.index.schema;
import java.util.StringJoiner;
import org.neo4j.io.pagecache.PageCursor;
import org.neo4j.util.Preconditions;
import org.neo4j.values.storable.Value;
import org.neo4j.values.storable.ValueGroup;
/**
* {@link RangeKey} which has an array of {@link RangeKey} inside and can therefore hold composite key state.
* For single-keys please instead use the more efficient {@link RangeKey}.
*/
final class CompositeRangeKey extends RangeKey
{
private RangeKey[] states;
CompositeRangeKey( int slots )
{
states = new RangeKey[slots];
for ( int i = 0; i < slots; i++ )
{
states[i] = new RangeKey();
}
}
@Override
void writeValue( int stateSlot, Value value, Inclusion inclusion )
{
stateSlot( stateSlot ).writeValue( value, inclusion );
}
@Override
void assertValidValue( int stateSlot, Value value )
{
Preconditions.requireBetween( stateSlot, 0, numberOfStateSlots() );
}
@Override
Value[] asValues()
{
Value[] values = new Value[numberOfStateSlots()];
for ( int i = 0; i < values.length; i++ )
{
values[i] = stateSlot( i ).asValue();
}
return values;
}
@Override
void initValueAsLowest( int stateSlot, ValueGroup valueGroup )
{
stateSlot( stateSlot ).initValueAsLowest( valueGroup );
}
@Override
void initValueAsHighest( int stateSlot, ValueGroup valueGroup )
{
stateSlot( stateSlot ).initValueAsHighest( valueGroup );
}
@Override
int compareValueToInternal( RangeKey other )
{
int slots = numberOfStateSlots();
for ( int i = 0; i < slots; i++ )
{
int comparison = stateSlot( i ).compareValueToInternal( other.stateSlot( i ) );
if ( comparison != 0 )
{
return comparison;
}
}
return 0;
}
@Override
void copyFromInternal( GenericKey> key )
{
int slots = numberOfStateSlots();
if ( key.numberOfStateSlots() != slots )
{
throw new IllegalArgumentException( "Different state lengths " + key.numberOfStateSlots() + " vs " + slots );
}
for ( int i = 0; i < slots; i++ )
{
stateSlot( i ).copyFromInternal( key.stateSlot( i ) );
}
}
@Override
int sizeInternal()
{
int size = 0;
int slots = numberOfStateSlots();
for ( int i = 0; i < slots; i++ )
{
size += stateSlot( i ).sizeInternal();
}
return size;
}
@Override
void putInternal( PageCursor cursor )
{
int slots = numberOfStateSlots();
for ( int i = 0; i < slots; i++ )
{
stateSlot( i ).putInternal( cursor );
}
}
@Override
boolean getInternal( PageCursor cursor, int keySize )
{
int slots = numberOfStateSlots();
for ( int i = 0; i < slots; i++ )
{
if ( !stateSlot( i ).getInternal( cursor, keySize ) )
{
// The slot's getInternal has already set cursor exception, if it so desired, with more specific information so don't do it here.
return false;
}
}
return true;
}
@Override
void initializeToDummyValueInternal()
{
int slots = numberOfStateSlots();
for ( int i = 0; i < slots; i++ )
{
stateSlot( i ).initializeToDummyValueInternal();
}
}
@Override
int numberOfStateSlots()
{
return states.length;
}
@Override
public String toStringInternal()
{
StringJoiner joiner = new StringJoiner( "," );
for ( RangeKey state : states )
{
joiner.add( state.toStringInternal() );
}
return joiner.toString();
}
@Override
String toDetailedStringInternal()
{
StringJoiner joiner = new StringJoiner( "," );
for ( RangeKey state : states )
{
joiner.add( state.toDetailedStringInternal() );
}
return joiner.toString();
}
@Override
void minimalSplitterInternal( RangeKey left, RangeKey right, RangeKey into )
{
int firstStateToDiffer = 0;
int compare = 0;
int stateCount = right.numberOfStateSlots();
// It's really quite assumed that all these keys have the same number of state slots.
// It's not a practical runtime concern, so merely an assertion here
assert right.numberOfStateSlots() == stateCount;
assert into.numberOfStateSlots() == stateCount;
while ( compare == 0 && firstStateToDiffer < stateCount )
{
RangeKey leftState = left.stateSlot( firstStateToDiffer );
RangeKey rightState = right.stateSlot( firstStateToDiffer );
firstStateToDiffer++;
compare = leftState.compareValueToInternal( rightState );
}
firstStateToDiffer--; // Rewind last increment
for ( int i = 0; i < firstStateToDiffer; i++ )
{
into.stateSlot( i ).copyFromInternal( right.stateSlot( i ) );
}
for ( int i = firstStateToDiffer; i < stateCount; i++ )
{
RangeKey leftState = left.stateSlot( i );
RangeKey rightState = right.stateSlot( i );
rightState.minimalSplitterInternal( leftState, rightState, into.stateSlot( i ) );
}
}
@Override
RangeKey stateSlot( int slot )
{
return states[slot];
}
}