Skip to content

Commit

Permalink
Change so that endsWith, startsWith, and contains takes TextValue
Browse files Browse the repository at this point in the history
In order to reduce the number of encodings/decodings we should not create
string value until absolutely necessary.
  • Loading branch information
pontusmelke committed Nov 27, 2018
1 parent 6257b0e commit 6b539e7
Show file tree
Hide file tree
Showing 27 changed files with 150 additions and 142 deletions.
Expand Up @@ -84,6 +84,7 @@
import static org.neo4j.values.storable.Values.pointArray;
import static org.neo4j.values.storable.Values.pointValue;
import static org.neo4j.values.storable.Values.stringArray;
import static org.neo4j.values.storable.Values.stringValue;

@Ignore( "Not a test. This is a compatibility suite that provides test cases for verifying" +
" IndexProvider implementations. Each index provider that is to be tested by this suite" +
Expand Down Expand Up @@ -403,14 +404,14 @@ public void testIndexSeekExactWithPrefixRangeByString() throws Exception
add( 9L, descriptor.schema(), "b", "apA" ),
add( 10L, descriptor.schema(), "b", "b" ) ) );

assertThat( query( exact( 0, "a" ), IndexQuery.stringPrefix( 1, "a" ) ), equalTo( asList( 1L, 3L, 4L ) ) );
assertThat( query( exact( 0, "a" ), IndexQuery.stringPrefix( 1, "A" ) ), equalTo( Collections.singletonList( 2L ) ) );
assertThat( query( exact( 0, "a" ), IndexQuery.stringPrefix( 1, "ba" ) ), equalTo( EMPTY_LIST ) );
assertThat( query( exact( 0, "a" ), IndexQuery.stringPrefix( 1, "" ) ), equalTo( asList( 1L, 2L, 3L, 4L, 5L ) ) );
assertThat( query( exact( 0, "b" ), IndexQuery.stringPrefix( 1, "a" ) ), equalTo( asList( 6L, 8L, 9L ) ) );
assertThat( query( exact( 0, "b" ), IndexQuery.stringPrefix( 1, "A" ) ), equalTo( Collections.singletonList( 7L ) ) );
assertThat( query( exact( 0, "b" ), IndexQuery.stringPrefix( 1, "ba" ) ), equalTo( EMPTY_LIST ) );
assertThat( query( exact( 0, "b" ), IndexQuery.stringPrefix( 1, "" ) ), equalTo( asList( 6L, 7L, 8L, 9L, 10L ) ) );
assertThat( query( exact( 0, "a" ), IndexQuery.stringPrefix( 1, stringValue( "a" ) ) ), equalTo( asList( 1L, 3L, 4L ) ) );
assertThat( query( exact( 0, "a" ), IndexQuery.stringPrefix( 1, stringValue( "A" )) ), equalTo( Collections.singletonList( 2L ) ) );
assertThat( query( exact( 0, "a" ), IndexQuery.stringPrefix( 1, stringValue( "ba") ) ), equalTo( EMPTY_LIST ) );
assertThat( query( exact( 0, "a" ), IndexQuery.stringPrefix( 1, stringValue( "" )) ), equalTo( asList( 1L, 2L, 3L, 4L, 5L ) ) );
assertThat( query( exact( 0, "b" ), IndexQuery.stringPrefix( 1, stringValue( "a" )) ), equalTo( asList( 6L, 8L, 9L ) ) );
assertThat( query( exact( 0, "b" ), IndexQuery.stringPrefix( 1, stringValue( "A" )) ), equalTo( Collections.singletonList( 7L ) ) );
assertThat( query( exact( 0, "b" ), IndexQuery.stringPrefix( 1, stringValue( "ba") ) ), equalTo( EMPTY_LIST ) );
assertThat( query( exact( 0, "b" ), IndexQuery.stringPrefix( 1, stringValue( "" ) ) ), equalTo( asList( 6L, 7L, 8L, 9L, 10L ) ) );
}

@Test
Expand All @@ -431,10 +432,10 @@ public void testIndexSeekPrefixRangeWithExistsByString() throws Exception
add( 10L, descriptor.schema(), "b", false )
) );

assertThat( query( IndexQuery.stringPrefix( 0, "a" ), exists( 1 ) ), equalTo( asList( 1L, 3L, 4L, 6L, 8L, 9L ) ) );
assertThat( query( IndexQuery.stringPrefix( 0, "A" ), exists( 1 ) ), equalTo( asList( 2L, 7L) ) );
assertThat( query( IndexQuery.stringPrefix( 0, "ba" ), exists( 1 ) ), equalTo( EMPTY_LIST ) );
assertThat( query( IndexQuery.stringPrefix( 0, "" ), exists( 1 ) ), equalTo( asList( 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L ) ) );
assertThat( query( IndexQuery.stringPrefix( 0, stringValue( "a" )), exists( 1 ) ), equalTo( asList( 1L, 3L, 4L, 6L, 8L, 9L ) ) );
assertThat( query( IndexQuery.stringPrefix( 0, stringValue( "A" )), exists( 1 ) ), equalTo( asList( 2L, 7L) ) );
assertThat( query( IndexQuery.stringPrefix( 0, stringValue( "ba") ), exists( 1 ) ), equalTo( EMPTY_LIST ) );
assertThat( query( IndexQuery.stringPrefix( 0, stringValue( "" )), exists( 1 ) ), equalTo( asList( 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L ) ) );
}

/* testIndexSeekExactWithExists */
Expand Down
Expand Up @@ -77,6 +77,7 @@
import static org.neo4j.values.storable.LocalDateTimeValue.localDateTime;
import static org.neo4j.values.storable.LocalTimeValue.localTime;
import static org.neo4j.values.storable.TimeValue.time;
import static org.neo4j.values.storable.Values.stringValue;

@Ignore( "Not a test. This is a compatibility suite that provides test cases for verifying" +
" IndexProvider implementations. Each index provider that is to be tested by this suite" +
Expand All @@ -102,10 +103,10 @@ public void testIndexSeekByPrefix() throws Exception
add( 4L, descriptor.schema(), "apA" ),
add( 5L, descriptor.schema(), "b" ) ) );

assertThat( query( IndexQuery.stringPrefix( 1, "a" ) ), equalTo( asList( 1L, 3L, 4L ) ) );
assertThat( query( IndexQuery.stringPrefix( 1, "A" ) ), equalTo( singletonList( 2L ) ) );
assertThat( query( IndexQuery.stringPrefix( 1, "ba" ) ), equalTo( EMPTY_LIST ) );
assertThat( query( IndexQuery.stringPrefix( 1, "" ) ), equalTo( asList( 1L, 2L, 3L, 4L, 5L ) ) );
assertThat( query( IndexQuery.stringPrefix( 1, stringValue( "a" ) ) ), equalTo( asList( 1L, 3L, 4L ) ) );
assertThat( query( IndexQuery.stringPrefix( 1, stringValue( "A" ) ) ), equalTo( singletonList( 2L ) ) );
assertThat( query( IndexQuery.stringPrefix( 1, stringValue( "ba" ) ) ), equalTo( EMPTY_LIST ) );
assertThat( query( IndexQuery.stringPrefix( 1, stringValue( "" ) ) ), equalTo( asList( 1L, 2L, 3L, 4L, 5L ) ) );
}

@Test
Expand All @@ -115,7 +116,7 @@ public void testIndexSeekByPrefixOnNonStrings() throws Exception
add( 1L, descriptor.schema(), "2a" ),
add( 2L, descriptor.schema(), 2L ),
add( 2L, descriptor.schema(), 20L ) ) );
assertThat( query( IndexQuery.stringPrefix( 1, "2" ) ), equalTo( singletonList( 1L ) ) );
assertThat( query( IndexQuery.stringPrefix( 1, stringValue( "2" ) ) ), equalTo( singletonList( 1L ) ) );
}

@Test
Expand Down Expand Up @@ -996,8 +997,8 @@ public void testIndexRangeSeekByPrefixWithDuplicates() throws Exception
add( 4L, descriptor.schema(), "apa" ),
add( 5L, descriptor.schema(), "apa" ) ) );

assertThat( query( stringPrefix( 1, "a" ) ), equalTo( asList( 1L, 3L, 4L, 5L ) ) );
assertThat( query( stringPrefix( 1, "apa" ) ), equalTo( asList( 3L, 4L, 5L ) ) );
assertThat( query( stringPrefix( 1, stringValue( "a" ) ) ), equalTo( asList( 1L, 3L, 4L, 5L ) ) );
assertThat( query( stringPrefix( 1, stringValue( "apa" ) ) ), equalTo( asList( 3L, 4L, 5L ) ) );
}

@Test
Expand All @@ -1010,9 +1011,9 @@ public void testIndexFullSearchWithDuplicates() throws Exception
add( 4L, descriptor.schema(), "apa" ),
add( 5L, descriptor.schema(), "apalong" ) ) );

assertThat( query( stringContains( 1, "a" ) ), equalTo( asList( 1L, 3L, 4L, 5L ) ) );
assertThat( query( stringContains( 1, "apa" ) ), equalTo( asList( 3L, 4L, 5L ) ) );
assertThat( query( stringContains( 1, "apa*" ) ), equalTo( Collections.emptyList() ) );
assertThat( query( stringContains( 1, stringValue( "a" ) ) ), equalTo( asList( 1L, 3L, 4L, 5L ) ) );
assertThat( query( stringContains( 1, stringValue( "apa" ) ) ), equalTo( asList( 3L, 4L, 5L ) ) );
assertThat( query( stringContains( 1, stringValue( "apa*" ) ) ), equalTo( Collections.emptyList() ) );
}

@Test
Expand All @@ -1026,10 +1027,10 @@ public void testIndexEndsWithWithDuplicated() throws Exception
add( 5L, descriptor.schema(), "longapa" ),
add( 6L, descriptor.schema(), "apalong" ) ) );

assertThat( query( stringSuffix( 1, "a" ) ), equalTo( asList( 1L, 3L, 4L, 5L ) ) );
assertThat( query( stringSuffix( 1, "apa" ) ), equalTo( asList( 3L, 4L, 5L ) ) );
assertThat( query( stringSuffix( 1, "apa*" ) ), equalTo( Collections.emptyList() ) );
assertThat( query( stringSuffix( 1, "" ) ), equalTo( asList( 1L, 2L, 3L, 4L, 5L, 6L ) ) );
assertThat( query( stringSuffix( 1, stringValue( "a" ) ) ), equalTo( asList( 1L, 3L, 4L, 5L ) ) );
assertThat( query( stringSuffix( 1, stringValue( "apa" ) ) ), equalTo( asList( 3L, 4L, 5L ) ) );
assertThat( query( stringSuffix( 1, stringValue( "apa*" ) ) ), equalTo( Collections.emptyList() ) );
assertThat( query( stringSuffix( 1, stringValue( "" ) ) ), equalTo( asList( 1L, 2L, 3L, 4L, 5L, 6L ) ) );
}

@Test
Expand Down
Expand Up @@ -32,7 +32,7 @@ import org.neo4j.internal.kernel.api.{IndexQuery, IndexReference, NodeValueIndex
import org.neo4j.kernel.impl.api.store.RelationshipIterator
import org.neo4j.kernel.impl.core.EmbeddedProxySPI
import org.neo4j.values.AnyValue
import org.neo4j.values.storable.Value
import org.neo4j.values.storable.{TextValue, Value}
import org.neo4j.values.virtual.{ListValue, MapValue, NodeValue, RelationshipValue}
import org.opencypher.v9_0.expressions.SemanticDirection

Expand Down Expand Up @@ -248,13 +248,13 @@ class ExceptionTranslatingQueryContext(val inner: QueryContext) extends QueryCon
override def indexSeekByContains[RESULT <: AnyRef](index: IndexReference,
needsValues: Boolean,
indexOrder: IndexOrder,
value: String): NodeValueIndexCursor =
value: TextValue): NodeValueIndexCursor =
translateException(inner.indexSeekByContains(index, needsValues, indexOrder, value))

override def indexSeekByEndsWith[RESULT <: AnyRef](index: IndexReference,
needsValues: Boolean,
indexOrder: IndexOrder,
value: String): NodeValueIndexCursor =
value: TextValue): NodeValueIndexCursor =
translateException(inner.indexSeekByEndsWith(index, needsValues, indexOrder, value))

override def indexScan[RESULT <: AnyRef](index: IndexReference,
Expand Down
Expand Up @@ -20,6 +20,7 @@
package org.neo4j.cypher.internal.spi.v2_3

import java.net.URL
import java.nio.charset.StandardCharsets
import java.util.function.Predicate

import org.eclipse.collections.api.iterator.LongIterator
Expand Down Expand Up @@ -290,7 +291,7 @@ final class TransactionBoundQueryContext(tc: TransactionalContextWrapper, val re
}

private def indexSeekByPrefixRange(index: SchemaTypes.IndexDescriptor, prefix: String): scala.Iterator[Node] =
seek(tc.schemaRead.indexReferenceUnchecked(index.labelId, index.propertyId), IndexQuery.stringPrefix(index.propertyId, prefix))
seek(tc.schemaRead.indexReferenceUnchecked(index.labelId, index.propertyId), IndexQuery.stringPrefix(index.propertyId, Values.utf8Value( prefix.getBytes(StandardCharsets.UTF_8 ))))

private def indexSeekByNumericalRange(index: SchemaTypes.IndexDescriptor, range: InequalitySeekRange[Number]): scala.Iterator[Node] = (range match {
case rangeLessThan: RangeLessThan[Number] =>
Expand Down
Expand Up @@ -20,6 +20,7 @@
package org.neo4j.cypher.internal.spi.v3_1

import java.net.URL
import java.nio.charset.StandardCharsets.UTF_8
import java.util.function.Predicate

import org.eclipse.collections.api.iterator.LongIterator
Expand Down Expand Up @@ -60,6 +61,7 @@ import org.neo4j.kernel.impl.core.EmbeddedProxySPI
import org.neo4j.kernel.impl.util.ValueUtils
import org.neo4j.values.AnyValue
import org.neo4j.values.storable.Values
import org.neo4j.values.storable.Values.utf8Value

import scala.collection.Iterator
import scala.collection.JavaConverters._
Expand Down Expand Up @@ -285,7 +287,8 @@ final class TransactionBoundQueryContext(txContext: TransactionalContextWrapper,
}

private def indexSeekByPrefixRange(index: IndexDescriptor, prefix: String): scala.Iterator[Node] =
seek(txContext.kernelTransaction.schemaRead().indexReferenceUnchecked(index.labelId, index.propertyId), IndexQuery.stringPrefix(index.propertyId, prefix))
seek(txContext.kernelTransaction.schemaRead().indexReferenceUnchecked(index.labelId, index.propertyId),
IndexQuery.stringPrefix(index.propertyId, utf8Value(prefix.getBytes(UTF_8 ))))

private def indexSeekByNumericalRange(index: IndexDescriptor, range: InequalitySeekRange[Number]): scala.Iterator[Node] =(range match {
case rangeLessThan: RangeLessThan[Number] =>
Expand Down Expand Up @@ -354,10 +357,10 @@ final class TransactionBoundQueryContext(txContext: TransactionalContextWrapper,
}

override def indexScanByContains(index: IndexDescriptor, value: String) =
seek(txContext.kernelTransaction.schemaRead().indexReferenceUnchecked(index.labelId, index.propertyId), IndexQuery.stringContains(index.propertyId, value))
seek(txContext.kernelTransaction.schemaRead().indexReferenceUnchecked(index.labelId, index.propertyId), IndexQuery.stringContains(index.propertyId, utf8Value(value.getBytes(UTF_8))))

override def indexScanByEndsWith(index: IndexDescriptor, value: String) =
seek(txContext.kernelTransaction.schemaRead().indexReferenceUnchecked(index.labelId, index.propertyId), IndexQuery.stringSuffix(index.propertyId, value))
seek(txContext.kernelTransaction.schemaRead().indexReferenceUnchecked(index.labelId, index.propertyId), IndexQuery.stringSuffix(index.propertyId, utf8Value(value.getBytes(UTF_8))))

override def lockingUniqueIndexSeek(index: IndexDescriptor, value: Any): Option[Node] = {
indexSearchMonitor.lockingUniqueIndexSeek(index, value)
Expand Down
Expand Up @@ -24,14 +24,14 @@ import java.net.URL
import org.eclipse.collections.api.iterator.LongIterator
import org.neo4j.cypher.internal.planner.v3_5.spi.{IdempotentResult, IndexDescriptor}
import org.neo4j.cypher.internal.runtime._
import org.neo4j.cypher.internal.v3_5.logical.plans.IndexOrder
import org.neo4j.cypher.internal.v3_5.logical.plans.QualifiedName
import org.neo4j.cypher.internal.v3_5.logical.plans.{IndexOrder, QualifiedName}
import org.neo4j.graphdb.{Path, PropertyContainer}
import org.neo4j.internal.kernel.api.helpers.RelationshipSelectionCursor
import org.neo4j.internal.kernel.api.{IndexQuery, IndexReference, NodeValueIndexCursor}
import org.neo4j.kernel.impl.api.store.RelationshipIterator
import org.neo4j.kernel.impl.core.EmbeddedProxySPI
import org.neo4j.values.AnyValue
import org.neo4j.values.storable.TextValue
import org.neo4j.values.virtual.{ListValue, MapValue, NodeValue, RelationshipValue}
import org.opencypher.v9_0.expressions.SemanticDirection

Expand Down Expand Up @@ -243,12 +243,12 @@ abstract class BaseQueryContext extends QueryContext {
override def indexSeekByContains[RESULT <: AnyRef](index: IndexReference,
needsValues: Boolean,
indexOrder: IndexOrder,
value: String): NodeValueIndexCursor = notSupported()
value: TextValue): NodeValueIndexCursor = notSupported()

override def indexSeekByEndsWith[RESULT <: AnyRef](index: IndexReference,
needsValues: Boolean,
indexOrder: IndexOrder,
value: String): NodeValueIndexCursor = notSupported()
value: TextValue): NodeValueIndexCursor = notSupported()

override def indexScan[RESULT <: AnyRef](index: IndexReference,
needsValues: Boolean,
Expand Down
Expand Up @@ -33,7 +33,7 @@ import org.neo4j.kernel.impl.api.store.RelationshipIterator
import org.neo4j.kernel.impl.core.EmbeddedProxySPI
import org.neo4j.kernel.impl.factory.DatabaseInfo
import org.neo4j.values.AnyValue
import org.neo4j.values.storable.Value
import org.neo4j.values.storable.{TextValue, Value}
import org.neo4j.values.virtual.{ListValue, MapValue, NodeValue, RelationshipValue}
import org.opencypher.v9_0.expressions.SemanticDirection

Expand Down Expand Up @@ -134,13 +134,13 @@ abstract class DelegatingQueryContext(val inner: QueryContext) extends QueryCont
override def indexSeekByContains[RESULT <: AnyRef](index: IndexReference,
needsValues: Boolean,
indexOrder: IndexOrder,
value: String): NodeValueIndexCursor =
value: TextValue): NodeValueIndexCursor =
manyDbHits(inner.indexSeekByContains(index, needsValues, indexOrder, value))

override def indexSeekByEndsWith[RESULT <: AnyRef](index: IndexReference,
needsValues: Boolean,
indexOrder: IndexOrder,
value: String): NodeValueIndexCursor =
value: TextValue): NodeValueIndexCursor =
manyDbHits(inner.indexSeekByEndsWith(index, needsValues, indexOrder, value))

override def getNodesByLabel(id: Int): Iterator[NodeValue] = manyDbHits(inner.getNodesByLabel(id))
Expand Down
Expand Up @@ -38,13 +38,12 @@ import org.neo4j.graphdb.security.URLAccessValidationError
import org.neo4j.graphdb.traversal.{Evaluators, TraversalDescription, Uniqueness}
import org.neo4j.internal.kernel.api
import org.neo4j.internal.kernel.api.IndexQuery.ExactPredicate
import org.neo4j.internal.kernel.api.{IndexOrder => KernelIndexOrder, _}
import org.neo4j.internal.kernel.api._
import org.neo4j.internal.kernel.api.helpers.RelationshipSelections.{allCursor, incomingCursor, outgoingCursor}
import org.neo4j.internal.kernel.api.helpers._
import org.neo4j.internal.kernel.api.{IndexOrder => KernelIndexOrder, _}
import org.neo4j.io.IOUtils
import org.neo4j.kernel.GraphDatabaseQueryService
import org.neo4j.kernel.api.{ResourceManager => NotTheTypeWeWant, _}
import org.neo4j.kernel.api._
import org.neo4j.kernel.api.exceptions.schema.{AlreadyConstrainedException, AlreadyIndexedException}
import org.neo4j.kernel.api.schema.SchemaDescriptorFactory
import org.neo4j.kernel.api.schema.constraints.ConstraintDescriptorFactory
Expand Down Expand Up @@ -333,13 +332,13 @@ sealed class TransactionBoundQueryContext(val transactionalContext: Transactiona
override def indexSeekByContains[RESULT <: AnyRef](index: IndexReference,
needsValues: Boolean,
indexOrder: IndexOrder,
value: String): NodeValueIndexCursor =
value: TextValue): NodeValueIndexCursor =
seek(index, needsValues, indexOrder, IndexQuery.stringContains(index.properties()(0), value))

override def indexSeekByEndsWith[RESULT <: AnyRef](index: IndexReference,
needsValues: Boolean,
indexOrder: IndexOrder,
value: String): NodeValueIndexCursor =
value: TextValue): NodeValueIndexCursor =
seek(index, needsValues, indexOrder, IndexQuery.stringSuffix(index.properties()(0), value))

override def lockingUniqueIndexSeek[RESULT](indexReference: IndexReference,
Expand Down
Expand Up @@ -76,7 +76,7 @@ trait NodeIndexSeeker {
val expr = range.prefix
expr(row, state) match {
case text: TextValue =>
Array(Seq(IndexQuery.stringPrefix(propertyIds.head, text.stringValue())))
Array(Seq(IndexQuery.stringPrefix(propertyIds.head, text)))
case Values.NO_VALUE =>
Nil
case other =>
Expand Down

0 comments on commit 6b539e7

Please sign in to comment.