From bcb2e42dc78bc3aaa921d7a68c1fae0fe4053fa1 Mon Sep 17 00:00:00 2001 From: Sascha Peukert Date: Wed, 18 Jul 2018 16:04:53 +0200 Subject: [PATCH] Started enhancing query caches with parameter information --- .../org/neo4j/cypher/QueryCachingTest.scala | 8 ++- .../javacompat/MonitoringCacheTracer.java | 10 +-- .../cypher/PlanCacheMetricsMonitor.scala | 4 +- .../cypher/internal/ExecutionEngine.scala | 25 ++++---- .../neo4j/cypher/internal/QueryCache.scala | 4 +- .../neo4j/cypher/internal/SchemaHelper.scala | 2 +- .../compatibility/AstLogicalPlanCache.scala | 9 +-- .../internal/compatibility/BasePlanner.scala | 4 +- .../compatibility/v3_4/Cypher34Planner.scala | 6 +- .../compatibility/v3_5/Cypher35Planner.scala | 6 +- .../org/neo4j/values/storable/Values.java | 23 ++++++- .../org/neo4j/values/storable/ValuesTest.java | 63 +++++++++++++++++++ ...rStringCacheMonitoringAcceptanceTest.scala | 10 +-- 13 files changed, 136 insertions(+), 38 deletions(-) diff --git a/community/community-it/cypher-it/src/test/scala/org/neo4j/cypher/QueryCachingTest.scala b/community/community-it/cypher-it/src/test/scala/org/neo4j/cypher/QueryCachingTest.scala index b204d5db27ada..b75403c7ec547 100644 --- a/community/community-it/cypher-it/src/test/scala/org/neo4j/cypher/QueryCachingTest.scala +++ b/community/community-it/cypher-it/src/test/scala/org/neo4j/cypher/QueryCachingTest.scala @@ -21,7 +21,9 @@ package org.neo4j.cypher import org.neo4j.cypher.internal.StringCacheMonitor import org.neo4j.graphdb.Label +import org.neo4j.helpers.collection.Pair import org.neo4j.kernel.impl.core.ThreadToStatementContextBridge +import org.neo4j.values.virtual.MapValue import org.opencypher.v9_0.util.test_helpers.CypherFunSuite import org.scalatest.prop.TableDrivenPropertyChecks @@ -92,15 +94,15 @@ class QueryCachingTest extends CypherFunSuite with GraphDatabaseTestSupport with log += s"cacheFlushDetected" } - override def cacheHit(key: String): Unit = { + override def cacheHit(key: Pair[String, MapValue]): Unit = { log += s"cacheHit: $key" } - override def cacheMiss(key: String): Unit = { + override def cacheMiss(key: Pair[String, MapValue]): Unit = { log += s"cacheMiss: $key" } - override def cacheDiscard(key: String, ignored: String, secondsSinceReplan: Int): Unit = { + override def cacheDiscard(key: Pair[String, MapValue], ignored: String, secondsSinceReplan: Int): Unit = { log += s"cacheDiscard: $key" } } diff --git a/community/cypher/cypher/src/main/java/org/neo4j/cypher/internal/javacompat/MonitoringCacheTracer.java b/community/cypher/cypher/src/main/java/org/neo4j/cypher/internal/javacompat/MonitoringCacheTracer.java index 7c6a0a900f8e5..998efbb956699 100644 --- a/community/cypher/cypher/src/main/java/org/neo4j/cypher/internal/javacompat/MonitoringCacheTracer.java +++ b/community/cypher/cypher/src/main/java/org/neo4j/cypher/internal/javacompat/MonitoringCacheTracer.java @@ -21,11 +21,13 @@ import org.neo4j.cypher.internal.CacheTracer; import org.neo4j.cypher.internal.StringCacheMonitor; +import org.neo4j.helpers.collection.Pair; +import org.neo4j.values.virtual.MapValue; /** * Adapter for passing CacheTraces into the Monitoring infrastructure. */ -public class MonitoringCacheTracer implements CacheTracer +public class MonitoringCacheTracer implements CacheTracer> { private final StringCacheMonitor monitor; @@ -35,19 +37,19 @@ public MonitoringCacheTracer( StringCacheMonitor monitor ) } @Override - public void queryCacheHit( String queryKey, String metaData ) + public void queryCacheHit( Pair queryKey, String metaData ) { monitor.cacheHit( queryKey ); } @Override - public void queryCacheMiss( String queryKey, String metaData ) + public void queryCacheMiss( Pair queryKey, String metaData ) { monitor.cacheMiss( queryKey ); } @Override - public void queryCacheStale( String queryKey, int secondsSincePlan, String metaData ) + public void queryCacheStale( Pair queryKey, int secondsSincePlan, String metaData ) { monitor.cacheDiscard( queryKey, metaData, secondsSincePlan ); } diff --git a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/PlanCacheMetricsMonitor.scala b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/PlanCacheMetricsMonitor.scala index bb5089f3d5286..9263d874e4750 100644 --- a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/PlanCacheMetricsMonitor.scala +++ b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/PlanCacheMetricsMonitor.scala @@ -22,12 +22,14 @@ package org.neo4j.cypher import java.util.concurrent.atomic.AtomicLong import org.neo4j.cypher.internal.StringCacheMonitor +import org.neo4j.helpers.collection.Pair +import org.neo4j.values.virtual.MapValue class PlanCacheMetricsMonitor extends StringCacheMonitor { private val counter = new AtomicLong() private val waitTime = new AtomicLong() - override def cacheDiscard(ignored1: String, ignored2: String, secondsSinceReplan: Int): Unit = { + override def cacheDiscard(ignored1: Pair[String, MapValue], ignored2: String, secondsSinceReplan: Int): Unit = { counter.incrementAndGet() waitTime.addAndGet(secondsSinceReplan) } diff --git a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/ExecutionEngine.scala b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/ExecutionEngine.scala index 6263d6617e392..1400fac5f5ded 100644 --- a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/ExecutionEngine.scala +++ b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/ExecutionEngine.scala @@ -21,13 +21,13 @@ package org.neo4j.cypher.internal import java.time.Clock -import org.neo4j.cypher.internal.compatibility.{CypherCacheMonitor, LFUCache} -import org.opencypher.v9_0.frontend.phases.CompilationPhaseTracer -import org.neo4j.cypher.internal.runtime.interpreted.{LastCommittedTxIdProvider, ValueConversion} +import org.neo4j.cypher.internal.compatibility.CypherCacheMonitor +import org.neo4j.cypher.internal.runtime.interpreted.LastCommittedTxIdProvider import org.neo4j.cypher.internal.tracing.CompilationTracer import org.neo4j.cypher.internal.tracing.CompilationTracer.QueryCompilationEvent -import org.neo4j.cypher.{ParameterNotFoundException, SyntaxException, exceptionHandler} +import org.neo4j.cypher.{ParameterNotFoundException, exceptionHandler} import org.neo4j.graphdb.Result +import org.neo4j.helpers.collection.Pair import org.neo4j.internal.kernel.api.security.AccessMode import org.neo4j.kernel.GraphDatabaseQueryService import org.neo4j.kernel.impl.query.{QueryExecution, ResultBuffer, TransactionalContext} @@ -35,7 +35,7 @@ import org.neo4j.kernel.monitoring.Monitors import org.neo4j.logging.LogProvider import org.neo4j.values.virtual.MapValue -trait StringCacheMonitor extends CypherCacheMonitor[String] +trait StringCacheMonitor extends CypherCacheMonitor[Pair[String, MapValue]] /** * This class constructs and initializes both the cypher compilers and runtimes, which are very expensive @@ -44,7 +44,7 @@ trait StringCacheMonitor extends CypherCacheMonitor[String] class ExecutionEngine(val queryService: GraphDatabaseQueryService, val kernelMonitors: Monitors, val tracer: CompilationTracer, - val cacheTracer: CacheTracer[String], + val cacheTracer: CacheTracer[Pair[String, MapValue]], val config: CypherConfiguration, val compatibilityFactory: CompilerFactory, val logProvider: LogProvider, @@ -63,7 +63,7 @@ class ExecutionEngine(val queryService: GraphDatabaseQueryService, // Log on stale query discard from query cache private val log = logProvider.getLog( getClass ) kernelMonitors.addMonitorListener( new StringCacheMonitor { - override def cacheDiscard(ignored: String, query: String, secondsSinceReplan: Int) { + override def cacheDiscard(ignored: Pair[String, MapValue], query: String, secondsSinceReplan: Int) { log.info(s"Discarded stale query from the query cache after ${secondsSinceReplan} seconds: $query") } }) @@ -73,8 +73,8 @@ class ExecutionEngine(val queryService: GraphDatabaseQueryService, config.statsDivergenceCalculator, lastCommittedTxIdProvider, planReusabilitiy) - private val queryCache: QueryCache[String, ExecutableQuery] = - new QueryCache(config.queryCacheSize, planStalenessCaller, cacheTracer) + private val queryCache: QueryCache[String,Pair[String, MapValue], ExecutableQuery] = + new QueryCache[String, Pair[String, MapValue], ExecutableQuery](config.queryCacheSize, planStalenessCaller, cacheTracer) private val masterCompiler: MasterCompiler = new MasterCompiler(queryService, kernelMonitors, config, logProvider, new CompilerLibrary(compatibilityFactory)) @@ -91,7 +91,7 @@ class ExecutionEngine(val queryService: GraphDatabaseQueryService, try { val preParsedQuery = preParser.preParseQuery(query, profile) - val executableQuery = getOrCompile(context, preParsedQuery, queryTracer) + val executableQuery = getOrCompile(context, preParsedQuery, queryTracer, params) if (preParsedQuery.executionMode.name != "explain") { checkParameters(executableQuery.paramNames, params, executableQuery.extractedParams) } @@ -116,9 +116,10 @@ class ExecutionEngine(val queryService: GraphDatabaseQueryService, private def getOrCompile(context: TransactionalContext, preParsedQuery: PreParsedQuery, - tracer: QueryCompilationEvent + tracer: QueryCompilationEvent, + params: MapValue ): ExecutableQuery = { - val cacheKey = preParsedQuery.statementWithVersionAndPlanner + val cacheKey = Pair.of(preParsedQuery.statementWithVersionAndPlanner, params) // create transaction and query context val tc = context.getOrBeginNewIfClosed() diff --git a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/QueryCache.scala b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/QueryCache.scala index c9975ad69fd99..a246a3a7cab75 100644 --- a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/QueryCache.scala +++ b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/QueryCache.scala @@ -20,7 +20,9 @@ package org.neo4j.cypher.internal import com.github.benmanes.caffeine.cache.{Cache, Caffeine} +import org.neo4j.helpers.collection.Pair import org.neo4j.kernel.impl.query.TransactionalContext +import org.neo4j.values.virtual.MapValue /** * The result of one cache lookup. @@ -56,7 +58,7 @@ trait CacheTracer[QUERY_KEY] { * @param stalenessCaller Decided whether CachedExecutionPlans are stale * @param tracer Traces cache activity */ -class QueryCache[QUERY_KEY <: AnyRef, EXECUTABLE_QUERY <: AnyRef](val maximumSize: Int, +class QueryCache[QUERY_REP <: AnyRef, QUERY_KEY <: Pair[QUERY_REP, MapValue], EXECUTABLE_QUERY <: AnyRef](val maximumSize: Int, val stalenessCaller: PlanStalenessCaller[EXECUTABLE_QUERY], val tracer: CacheTracer[QUERY_KEY]) { diff --git a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/SchemaHelper.scala b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/SchemaHelper.scala index 3555a18fa92b0..fdc889aa58843 100644 --- a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/SchemaHelper.scala +++ b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/SchemaHelper.scala @@ -27,7 +27,7 @@ import org.neo4j.kernel.impl.query.TransactionalContext case class SchemaToken(x: Long) extends AnyVal -class SchemaHelper(val queryCache: QueryCache[_,_]) { +class SchemaHelper(val queryCache: QueryCache[_,_,_]) { private val schemaToken = new AtomicLong() diff --git a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/compatibility/AstLogicalPlanCache.scala b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/compatibility/AstLogicalPlanCache.scala index 37e8817b693ef..f22c2ef039a1f 100644 --- a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/compatibility/AstLogicalPlanCache.scala +++ b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/compatibility/AstLogicalPlanCache.scala @@ -21,9 +21,11 @@ package org.neo4j.cypher.internal.compatibility import java.time.Clock +import org.neo4j.cypher.internal._ import org.neo4j.cypher.internal.compiler.v3_5.StatsDivergenceCalculator import org.neo4j.cypher.internal.compiler.v3_5.phases.LogicalPlanState -import org.neo4j.cypher.internal._ +import org.neo4j.helpers.collection.Pair +import org.neo4j.values.virtual.MapValue /** * Cache which stores logical plans indexed by an AST statement. @@ -36,14 +38,13 @@ import org.neo4j.cypher.internal._ * @tparam STATEMENT Type of AST statement used as key */ class AstLogicalPlanCache[STATEMENT <: AnyRef](override val maximumSize: Int, - override val tracer: CacheTracer[STATEMENT], + override val tracer: CacheTracer[Pair[STATEMENT, MapValue]], clock: Clock, divergence: StatsDivergenceCalculator, lastCommittedTxIdProvider: () => Long -) extends QueryCache[STATEMENT, CacheableLogicalPlan](maximumSize, +) extends QueryCache[STATEMENT,Pair[STATEMENT,MapValue], CacheableLogicalPlan](maximumSize, AstLogicalPlanCache.stalenessCaller(clock, divergence, lastCommittedTxIdProvider), tracer) - object AstLogicalPlanCache { def stalenessCaller(clock: Clock, divergence: StatsDivergenceCalculator, diff --git a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/compatibility/BasePlanner.scala b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/compatibility/BasePlanner.scala index 4377ec86f8b36..d5f64df45603a 100644 --- a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/compatibility/BasePlanner.scala +++ b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/compatibility/BasePlanner.scala @@ -26,8 +26,10 @@ import org.neo4j.cypher.internal.compatibility.v3_5.{WrappedMonitors => WrappedM import org.neo4j.cypher.internal.compiler.v3_5._ import org.neo4j.cypher.internal.compiler.v3_5.phases.LogicalPlanState import org.neo4j.cypher.internal.planner.v3_5.spi.PlanContext +import org.neo4j.helpers.collection.Pair import org.neo4j.kernel.monitoring.{Monitors => KernelMonitors} import org.neo4j.logging.Log +import org.neo4j.values.virtual.MapValue import org.opencypher.v9_0.frontend.phases._ /** @@ -47,7 +49,7 @@ abstract class BasePlanner[STATEMENT <: AnyRef, PARSED_STATE <: AnyRef]( protected val logger: InfoLogger = new StringInfoLogger(log) protected val monitors: Monitors = WrappedMonitorsv3_5(kernelMonitors) - protected val cacheTracer: CacheTracer[STATEMENT] = monitors.newMonitor[CacheTracer[STATEMENT]]("cypher3.5") + protected val cacheTracer: CacheTracer[Pair[STATEMENT, MapValue]] = monitors.newMonitor[CacheTracer[Pair[STATEMENT, MapValue]]]("cypher3.5") override def parserCacheSize: Int = config.queryCacheSize diff --git a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/compatibility/v3_4/Cypher34Planner.scala b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/compatibility/v3_4/Cypher34Planner.scala index d4a7cd1587cad..b6e765ee3f28c 100644 --- a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/compatibility/v3_4/Cypher34Planner.scala +++ b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/compatibility/v3_4/Cypher34Planner.scala @@ -47,6 +47,7 @@ import org.neo4j.cypher.internal.util.{v3_4 => utilV3_4} import org.neo4j.cypher.internal.v3_4.expressions.{Expression, Parameter} import org.neo4j.cypher.{CypherPlannerOption, CypherUpdateStrategy, CypherVersion} import org.neo4j.graphdb.Notification +import org.neo4j.helpers.collection.Pair import org.neo4j.kernel.impl.query.TransactionalContext import org.neo4j.kernel.monitoring.{Monitors => KernelMonitors} import org.neo4j.logging.Log @@ -205,9 +206,10 @@ case class Cypher34Planner(configv3_5: CypherPlannerConfiguration, CacheableLogicalPlan(logicalPlanStatev3_5, reusabilityState) } + val params = ValueConversion.asValues(preparedQuery.extractedParams()) val cacheableLogicalPlan = if (preParsedQuery.debugOptions.isEmpty) - planCache.computeIfAbsentOrStale(syntacticQuery.statement(), + planCache.computeIfAbsentOrStale(Pair.of(syntacticQuery.statement(), params), transactionalContext, createPlan, syntacticQuery.queryText).executableQuery @@ -220,7 +222,7 @@ case class Cypher34Planner(configv3_5: CypherPlannerConfiguration, LogicalPlanResult( cacheableLogicalPlan.logicalPlanState, queryParamNames, - ValueConversion.asValues(preparedQuery.extractedParams()), + params, cacheableLogicalPlan.reusability, contextv3_5) } diff --git a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/compatibility/v3_5/Cypher35Planner.scala b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/compatibility/v3_5/Cypher35Planner.scala index dc71af8155985..e497ab219796b 100644 --- a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/compatibility/v3_5/Cypher35Planner.scala +++ b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/compatibility/v3_5/Cypher35Planner.scala @@ -34,6 +34,7 @@ import org.neo4j.cypher.internal.compiler.v3_5.planner.logical.{CachedMetricsFac import org.neo4j.cypher.internal.planner.v3_5.spi.{CostBasedPlannerName, DPPlannerName, IDPPlannerName, PlanContext} import org.neo4j.cypher.internal.runtime.interpreted._ import org.neo4j.graphdb.Notification +import org.neo4j.helpers.collection.Pair import org.neo4j.kernel.impl.query.TransactionalContext import org.neo4j.kernel.monitoring.{Monitors => KernelMonitors} import org.neo4j.logging.Log @@ -152,9 +153,10 @@ case class Cypher35Planner(config: CypherPlannerConfiguration, CacheableLogicalPlan(logicalPlanState, reusabilityState) } + val params= ValueConversion.asValues(preparedQuery.extractedParams()) val cacheableLogicalPlan = if (preParsedQuery.debugOptions.isEmpty) - planCache.computeIfAbsentOrStale(syntacticQuery.statement(), + planCache.computeIfAbsentOrStale(Pair.of(syntacticQuery.statement(), params), transactionalContext, createPlan, syntacticQuery.queryText).executableQuery @@ -164,7 +166,7 @@ case class Cypher35Planner(config: CypherPlannerConfiguration, LogicalPlanResult( cacheableLogicalPlan.logicalPlanState, queryParamNames, - ValueConversion.asValues(preparedQuery.extractedParams()), + params, cacheableLogicalPlan.reusability, context) } diff --git a/community/values/src/main/java/org/neo4j/values/storable/Values.java b/community/values/src/main/java/org/neo4j/values/storable/Values.java index 946381527bb50..aaa7b011a012b 100644 --- a/community/values/src/main/java/org/neo4j/values/storable/Values.java +++ b/community/values/src/main/java/org/neo4j/values/storable/Values.java @@ -32,13 +32,13 @@ import java.time.temporal.TemporalAmount; import java.time.temporal.TemporalUnit; import java.util.Arrays; -import java.util.Comparator; import java.util.List; import java.util.Objects; import org.neo4j.graphdb.spatial.CRS; import org.neo4j.graphdb.spatial.Point; -import org.neo4j.values.TernaryComparator; +import org.neo4j.values.AnyValue; +import org.neo4j.values.virtual.MapValue; import static java.lang.String.format; import static org.neo4j.values.storable.DateTimeValue.datetime; @@ -750,4 +750,23 @@ public static Value maxValue( ValueGroup valueGroup, Value value ) format( "The maxValue for valueGroup %s is not defined yet", valueGroup ) ); } } + + public static boolean mapsEqualsOnValueTypes( MapValue one, MapValue other ) + { + if ( other.size() != one.size() ) + { + return false; + } + + for ( String key : one.keySet() ) + { + AnyValue oneValue = one.get( key ); + AnyValue otherValue = other.get( key ); + if ( !(oneValue.getClass() == otherValue.getClass()) ) + { + return false; + } + } + return true; + } } diff --git a/community/values/src/test/java/org/neo4j/values/storable/ValuesTest.java b/community/values/src/test/java/org/neo4j/values/storable/ValuesTest.java index 242e9ba5dee50..0d1570678646f 100644 --- a/community/values/src/test/java/org/neo4j/values/storable/ValuesTest.java +++ b/community/values/src/test/java/org/neo4j/values/storable/ValuesTest.java @@ -21,7 +21,12 @@ import org.junit.jupiter.api.Test; +import org.neo4j.values.virtual.MapValue; +import org.neo4j.values.virtual.MapValueBuilder; + +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.neo4j.values.storable.Values.booleanArray; import static org.neo4j.values.storable.Values.booleanValue; import static org.neo4j.values.storable.Values.byteArray; @@ -95,4 +100,62 @@ void pointValueShouldRequireConsistentInput() assertThrows(IllegalArgumentException.class, () -> Values.pointValue( CoordinateReferenceSystem.WGS84, 1, 2, 3 ) ); assertThrows(IllegalArgumentException.class, () -> Values.pointValue( CoordinateReferenceSystem.WGS84_3D, 1, 2 ) ); } + + @Test + void mapsShouldBeEqualOnValueTypes() + { + MapValueBuilder builder = new MapValueBuilder(); + builder.add( "prop1", stringValue( "value" ) ); + builder.add( "prop2", intValue( 1 ) ); + builder.add( "prop3", longValue( 1L ) ); + builder.add( "prop4", booleanArray( new boolean[]{true} ) ); + builder.add( "prop5", stringArray( "hi" ) ); + + MapValue map = builder.build(); + + assertTrue( Values.mapsEqualsOnValueTypes( map, map ) ); + } + + @Test + void mapsShouldNotBeEqualOnValueTypes() + { + MapValueBuilder builder = new MapValueBuilder(); + builder.add( "prop1", stringValue( "value" ) ); + builder.add( "prop2", intValue( 1 ) ); + builder.add( "prop3", longValue( 1L ) ); + builder.add( "prop4", booleanArray( new boolean[]{true} ) ); + builder.add( "prop5", stringArray( "hi" ) ); + MapValue map1 = builder.build(); + + builder = new MapValueBuilder(); + MapValue map2 = builder.build(); + + assertFalse( Values.mapsEqualsOnValueTypes( map1, map2 ) ); + assertFalse( Values.mapsEqualsOnValueTypes( map2, map1 ) ); + + // Compare with almost the same maps + // -> not all keys + builder = new MapValueBuilder(); + builder.add( "prop1", stringValue( "value" ) ); + builder.add( "prop2", intValue( 1 ) ); + builder.add( "prop4", booleanArray( new boolean[]{true} ) ); + builder.add( "prop3", longValue( 1L ) ); + MapValue map3 = builder.build(); + + assertFalse( Values.mapsEqualsOnValueTypes( map1, map3 ) ); + assertFalse( Values.mapsEqualsOnValueTypes( map3, map1 ) ); + + // -> some different value types + builder = new MapValueBuilder(); + builder.add( "prop1", stringValue( "value" ) ); + builder.add( "prop2", longValue( 1L ) ); + builder.add( "prop4", booleanArray( new boolean[]{true} ) ); + builder.add( "prop3", intValue( 1 ) ); + builder.add( "prop5", stringArray( "hi" ) ); + MapValue map4 = builder.build(); + + assertFalse( Values.mapsEqualsOnValueTypes( map1, map4 ) ); + assertFalse( Values.mapsEqualsOnValueTypes( map4, map1 ) ); + + } } diff --git a/enterprise/cypher/acceptance-spec-suite/src/test/scala/org/neo4j/internal/cypher/acceptance/CypherCompilerStringCacheMonitoringAcceptanceTest.scala b/enterprise/cypher/acceptance-spec-suite/src/test/scala/org/neo4j/internal/cypher/acceptance/CypherCompilerStringCacheMonitoringAcceptanceTest.scala index c7c4beb71983d..bd44f99ae56f9 100644 --- a/enterprise/cypher/acceptance-spec-suite/src/test/scala/org/neo4j/internal/cypher/acceptance/CypherCompilerStringCacheMonitoringAcceptanceTest.scala +++ b/enterprise/cypher/acceptance-spec-suite/src/test/scala/org/neo4j/internal/cypher/acceptance/CypherCompilerStringCacheMonitoringAcceptanceTest.scala @@ -28,9 +28,9 @@ import org.neo4j.cypher.ExecutionEngineHelper.createEngine import org.neo4j.cypher.internal.{ExecutionEngine, StringCacheMonitor} import org.neo4j.graphdb.config.Setting import org.neo4j.graphdb.factory.GraphDatabaseSettings -import org.neo4j.kernel.api +import org.neo4j.helpers.collection.Pair import org.neo4j.logging.AssertableLogProvider -import org.neo4j.values.virtual.VirtualValues +import org.neo4j.values.virtual.{MapValue, VirtualValues} import scala.collection.Map @@ -41,11 +41,11 @@ class CypherCompilerStringCacheMonitoringAcceptanceTest extends ExecutionEngineF } class CacheCounter(var counts: CacheCounts = CacheCounts()) extends StringCacheMonitor { - override def cacheMiss(key: String) { + override def cacheMiss(key: Pair[String, MapValue]) { counts = counts.copy(misses = counts.misses + 1) } - override def cacheHit(key: String) { + override def cacheHit(key: Pair[String, MapValue]) { counts = counts.copy(hits = counts.hits + 1) } @@ -53,7 +53,7 @@ class CypherCompilerStringCacheMonitoringAcceptanceTest extends ExecutionEngineF counts = counts.copy(flushes = counts.flushes + 1) } - override def cacheDiscard(key: String, key2: String, secondsSinceReplan: Int) { + override def cacheDiscard(key: Pair[String, MapValue], key2: String, secondsSinceReplan: Int) { counts = counts.copy(evicted = counts.evicted + 1) } }