diff --git a/community/cypher/acceptance-spec-suite/src/test/scala/org/neo4j/internal/cypher/acceptance/MatchLongPatternAcceptanceTest.scala b/community/cypher/acceptance-spec-suite/src/test/scala/org/neo4j/internal/cypher/acceptance/MatchLongPatternAcceptanceTest.scala index 90a5a46447d43..c942e723c0abf 100644 --- a/community/cypher/acceptance-spec-suite/src/test/scala/org/neo4j/internal/cypher/acceptance/MatchLongPatternAcceptanceTest.scala +++ b/community/cypher/acceptance-spec-suite/src/test/scala/org/neo4j/internal/cypher/acceptance/MatchLongPatternAcceptanceTest.scala @@ -22,7 +22,7 @@ package org.neo4j.internal.cypher.acceptance import java.util import org.neo4j.cypher._ -import org.neo4j.cypher.internal.compatibility.CompatibilityPlanDescriptionFor3_1 +import org.neo4j.cypher.internal.compatibility.CompatibilityPlanDescriptionFor3_2 import org.neo4j.cypher.internal.compiler.v3_2.planDescription.InternalPlanDescription import org.neo4j.cypher.internal.compiler.v3_2.planner.logical.idp.IDPSolverMonitor import org.neo4j.cypher.internal.compiler.v3_2.{IDPPlannerName, InterpretedRuntimeName} @@ -162,7 +162,7 @@ class MatchLongPatternAcceptanceTest extends ExecutionEngineFunSuite with QueryS } private def assertMinExpandsAndJoins(plan: InternalPlanDescription, minCounts: Map[String, Int]): Map[String, Int] = { - val externalPlanDescription = CompatibilityPlanDescriptionFor3_1(plan, CypherVersion.v3_1, IDPPlannerName, InterpretedRuntimeName) + val externalPlanDescription = CompatibilityPlanDescriptionFor3_2(plan, CypherVersion.v3_2, IDPPlannerName, InterpretedRuntimeName) assertMinExpandsAndJoins(externalPlanDescription, minCounts) } @@ -176,7 +176,7 @@ class MatchLongPatternAcceptanceTest extends ExecutionEngineFunSuite with QueryS } private def countExpandsAndJoins(plan: InternalPlanDescription): Map[String, Int] = { - val externalPlanDescription = CompatibilityPlanDescriptionFor3_1(plan, CypherVersion.v3_1, IDPPlannerName, InterpretedRuntimeName) + val externalPlanDescription = CompatibilityPlanDescriptionFor3_2(plan, CypherVersion.v3_2, IDPPlannerName, InterpretedRuntimeName) countExpandsAndJoins(externalPlanDescription) } diff --git a/community/cypher/compatibility-spec-suite/src/test/java/cypher/CompatibilitySpecSuiteTest.java b/community/cypher/compatibility-spec-suite/src/test/java/cypher/CompatibilitySpecSuiteTest.java index f79dce3c9cd6e..30bc42bc627a4 100644 --- a/community/cypher/compatibility-spec-suite/src/test/java/cypher/CompatibilitySpecSuiteTest.java +++ b/community/cypher/compatibility-spec-suite/src/test/java/cypher/CompatibilitySpecSuiteTest.java @@ -24,11 +24,7 @@ import org.junit.runner.RunWith; import org.opencypher.tools.tck.TCKCucumberTemplate; -import static cypher.SpecSuiteConstants.BLACKLIST_PLUGIN; -import static cypher.SpecSuiteConstants.DB_CONFIG; -import static cypher.SpecSuiteConstants.GLUE_PATH; -import static cypher.SpecSuiteConstants.HTML_REPORT; -import static cypher.SpecSuiteConstants.JSON_REPORT; +import static cypher.SpecSuiteConstants.*; @RunWith( CompatibilitySpecSuiteResources.class ) public class CompatibilitySpecSuiteTest @@ -114,17 +110,17 @@ public static class Compatibility23 @RunWith( Cucumber.class ) @CucumberOptions( plugin = { - DB_CONFIG + "compatibility-30.json", - HTML_REPORT + SUITE_NAME + "/compatibility-30", - JSON_REPORT + SUITE_NAME + "/compatibility-30", - BLACKLIST_PLUGIN + "compatibility-30.txt" + DB_CONFIG + "compatibility-31.json", + HTML_REPORT + SUITE_NAME + "/compatibility-31", + JSON_REPORT + SUITE_NAME + "/compatibility-31", + BLACKLIST_PLUGIN + "compatibility-31.txt" }, glue = { GLUE_PATH }, features = { FEATURE_PATH + FEATURE_TO_RUN }, tags = { "~@pending" }, strict = true ) - public static class Compatibility30 + public static class Compatibility31 { } diff --git a/community/cypher/compatibility-spec-suite/src/test/resources/blacklists/compatibility-30.txt b/community/cypher/compatibility-spec-suite/src/test/resources/blacklists/compatibility-30.txt deleted file mode 100644 index 03633df3ce39e..0000000000000 --- a/community/cypher/compatibility-spec-suite/src/test/resources/blacklists/compatibility-30.txt +++ /dev/null @@ -1,75 +0,0 @@ -// missing toInteger() -Number-typed integer comparison -Number-typed float comparison -Any-typed string comparison -Use collection lookup based on parameters when there is rhs type information -SKIP with an expression that does not depend on variables -LIMIT with an expression that does not depend on variables -`toInteger()` -`toInteger()` on float -`toInteger()` returning null on non-numerical string -`toInteger()` handling mixed number types -`toInteger()` handling Any type -`toInteger()` on a list of strings -`toInteger()` failing on invalid arguments - -// missing toBoolean() -`toBoolean()` on valid literal string -`toBoolean()` on booleans -`toBoolean()` on variables with valid string values -`toBoolean()` on invalid strings -`toBoolean()` on invalid types - -// new parameter syntax $ -Delete node from a list -Delete node from a list -Delete relationship from a list -Use dynamic property lookup based on parameters when there is no type information -Use dynamic property lookup based on parameters when there is lhs type information -Use dynamic property lookup based on parameters when there is rhs type information -Use collection lookup based on parameters when there is no type information -Use collection lookup based on parameters when there is lhs type information -Fail at runtime when attempting to index with an Int into a Map -Fail at runtime when trying to index into a map with a non-string -Fail at runtime when attempting to index with a String into a Collection -Fail at runtime when trying to index into a list with a list -Fail at runtime when trying to index something which is not a map or collection -`percentileDisc()` -`percentileCont()` -`percentileCont()` failing on bad arguments -`percentileDisc()` failing on bad arguments -`percentileDisc()` failing in more involved query -Using `keys()` on a parameter map -Use params in pattern matching predicates -Matching with many predicates and larger pattern -ORDER BY with negative parameter for LIMIT should not generate errors -Start the result from the second row by param -Get rows in the middle by param -Using null in AND -Using null in OR -Using null in XOR -Using null in IN -Creating nodes from an unwound parameter list -Unwind with merge - -// unsupported pattern comprehensions -Pattern comprehension and ORDER BY -Returning a pattern comprehension -Returning a pattern comprehension with label predicate -Returning a pattern comprehension with bound nodes -Using a pattern comprehension in a WITH -Using a variable-length pattern comprehension in a WITH -Using pattern comprehension in RETURN -Aggregating on pattern comprehension -Using pattern comprehension to test existence -Pattern comprehension inside list comprehension -Get node degree via size of pattern comprehension -Get node degree via size of pattern comprehension that specifies a relationship type -Get node degree via size of pattern comprehension that specifies multiple relationship types -Introducing new node variable in pattern comprehension -Introducing new relationship variable in pattern comprehension - -// bugged in spec, awaiting update -SKIP with an expression that depends on variables should fail -LIMIT with an expression that depends on variables should fail -Fail when returning type of deleted relationships diff --git a/community/cypher/compatibility-spec-suite/src/test/resources/blacklists/compatibility-31.txt b/community/cypher/compatibility-spec-suite/src/test/resources/blacklists/compatibility-31.txt new file mode 100644 index 0000000000000..fd85240be0064 --- /dev/null +++ b/community/cypher/compatibility-spec-suite/src/test/resources/blacklists/compatibility-31.txt @@ -0,0 +1,5 @@ +// bugged in spec, awaiting update +SKIP with an expression that depends on variables should fail +LIMIT with an expression that depends on variables should fail +Fail when returning type of deleted relationships +Fail when returning properties of deleted relationships diff --git a/community/cypher/compatibility-spec-suite/src/test/resources/db-config/compatibility-30.json b/community/cypher/compatibility-spec-suite/src/test/resources/db-config/compatibility-30.json deleted file mode 100644 index 6410697be6e78..0000000000000 --- a/community/cypher/compatibility-spec-suite/src/test/resources/db-config/compatibility-30.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "language": "3.0" -} diff --git a/community/cypher/compatibility-spec-suite/src/test/resources/db-config/compatibility-31.json b/community/cypher/compatibility-spec-suite/src/test/resources/db-config/compatibility-31.json new file mode 100644 index 0000000000000..b30723d6fa741 --- /dev/null +++ b/community/cypher/compatibility-spec-suite/src/test/resources/db-config/compatibility-31.json @@ -0,0 +1,3 @@ +{ + "language": "3.1" +} diff --git a/community/cypher/cypher/pom.xml b/community/cypher/cypher/pom.xml index 360d4b7325dfe..13ae7c2538c8b 100644 --- a/community/cypher/cypher/pom.xml +++ b/community/cypher/cypher/pom.xml @@ -215,8 +215,8 @@ org.neo4j - neo4j-cypher-compiler-3.0 - 3.0.6 + neo4j-cypher-compiler-3.1 + 3.1.0-M12-beta2 org.neo4j diff --git a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/CypherVersion.scala b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/CypherVersion.scala index e438e8bf24b2b..ce178486a6b43 100644 --- a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/CypherVersion.scala +++ b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/CypherVersion.scala @@ -23,9 +23,9 @@ sealed abstract class CypherVersion(versionName: String) extends CypherOption(ve case object CypherVersion extends CypherOptionCompanion[CypherVersion] { case object v2_3 extends CypherVersion("2.3") - case object v3_0 extends CypherVersion("3.0") case object v3_1 extends CypherVersion("3.1") + case object v3_2 extends CypherVersion("3.2") - val default = v3_1 - val all: Set[CypherVersion] = Set(v2_3, v3_0, v3_1) + val default = v3_2 + val all: Set[CypherVersion] = Set(v2_3, v3_1, v3_2) } diff --git a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/CypherCompiler.scala b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/CypherCompiler.scala index 1d358dfc753ff..d095f1ef04a4c 100644 --- a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/CypherCompiler.scala +++ b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/CypherCompiler.scala @@ -21,7 +21,7 @@ package org.neo4j.cypher.internal import java.time.Clock -import org.neo4j.cypher.internal.compatibility.exceptionHandlerFor3_1 +import org.neo4j.cypher.internal.compatibility.exceptionHandlerFor3_2 import org.neo4j.cypher.internal.compiler.v3_2._ import org.neo4j.cypher.internal.frontend.v3_2.InputPosition import org.neo4j.cypher.{InvalidArgumentException, SyntaxException, _} @@ -95,7 +95,7 @@ class CypherCompiler(graph: GraphDatabaseQueryService, private final val ILLEGAL_PLANNER_RUNTIME_COMBINATIONS: Set[(CypherPlanner, CypherRuntime)] = Set((CypherPlanner.rule, CypherRuntime.compiled)) @throws(classOf[SyntaxException]) - def preParseQuery(queryText: String): PreParsedQuery = exceptionHandlerFor3_1.runSafely { + def preParseQuery(queryText: String): PreParsedQuery = exceptionHandlerFor3_2.runSafely { val preParsedStatement = CypherPreParser(queryText) val CypherStatementWithOptions(statement, offset, version, planner, runtime, updateStrategy, mode) = CypherStatementWithOptions(preParsedStatement) @@ -128,14 +128,14 @@ class CypherCompiler(graph: GraphDatabaseQueryService, @throws(classOf[SyntaxException]) def parseQuery(preParsedQuery: PreParsedQuery, tracer: CompilationPhaseTracer): ParsedQuery = { import helpers.wrappersFor2_3._ - import helpers.wrappersFor3_0._ + import helpers.wrappersFor3_1._ val planner = preParsedQuery.planner val runtime = preParsedQuery.runtime val updateStrategy = preParsedQuery.updateStrategy preParsedQuery.version match { - case CypherVersion.v3_1 => planners(PlannerSpec_v3_1(planner, runtime, updateStrategy)).produceParsedQuery(preParsedQuery, tracer) - case CypherVersion.v3_0 => planners(PlannerSpec_v3_0(planner, runtime, updateStrategy)).produceParsedQuery(preParsedQuery, as3_0(tracer)) + case CypherVersion.v3_2 => planners(PlannerSpec_v3_2(planner, runtime, updateStrategy)).produceParsedQuery(preParsedQuery, tracer) + case CypherVersion.v3_1 => planners(PlannerSpec_v3_1(planner, runtime, updateStrategy)).produceParsedQuery(preParsedQuery, as3_1(tracer)) case CypherVersion.v2_3 => planners(PlannerSpec_v2_3(planner, runtime)).produceParsedQuery(preParsedQuery, as2_3(tracer)) } } 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 6a544c5219427..3ed89010a2fa7 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 @@ -22,15 +22,15 @@ package org.neo4j.cypher.internal import java.util.{Map => JavaMap} import org.neo4j.cypher._ +import org.neo4j.cypher.internal.compiler.v3_2._ import org.neo4j.cypher.internal.compiler.v3_2.helpers.{RuntimeJavaValueConverter, RuntimeScalaValueConverter} import org.neo4j.cypher.internal.compiler.v3_2.prettifier.Prettifier -import org.neo4j.cypher.internal.compiler.v3_2.{LFUCache => LRUCachev3_1, _} -import org.neo4j.cypher.internal.spi.TransactionalContextWrapperv3_1 +import org.neo4j.cypher.internal.spi.TransactionalContextWrapperv3_2 import org.neo4j.cypher.internal.tracing.{CompilationTracer, TimingCompilationTracer} import org.neo4j.graphdb.config.Setting import org.neo4j.graphdb.factory.GraphDatabaseSettings import org.neo4j.kernel.api.ReadOperations -import org.neo4j.kernel.api.security.{AccessMode, SecurityContext} +import org.neo4j.kernel.api.security.AccessMode import org.neo4j.kernel.configuration.Config import org.neo4j.kernel.impl.query.{QueryExecutionMonitor, TransactionalContext} import org.neo4j.kernel.{GraphDatabaseQueryService, api, monitoring} @@ -71,8 +71,8 @@ class ExecutionEngine(val queryService: GraphDatabaseQueryService, logProvider: private val cacheAccessor = new MonitoringCacheAccessor[String, (ExecutionPlan, Map[String, Any])](cacheMonitor) - private val preParsedQueries = new LRUCachev3_1[String, PreParsedQuery](getPlanCacheSize) - private val parsedQueries = new LRUCachev3_1[String, ParsedQuery](getPlanCacheSize) + private val preParsedQueries = new LFUCache[String, PreParsedQuery](getPlanCacheSize) + private val parsedQueries = new LFUCache[String, ParsedQuery](getPlanCacheSize) private val javaValues = new RuntimeJavaValueConverter(isGraphKernelResultValue, identity) private val scalaValues = new RuntimeScalaValueConverter(isGraphKernelResultValue, identity) @@ -126,14 +126,14 @@ class ExecutionEngine(val queryService: GraphDatabaseQueryService, logProvider: preParsedQueries.getOrElseUpdate(queryText, compiler.preParseQuery(queryText)) @throws(classOf[SyntaxException]) - protected def planQuery(transactionalContext: TransactionalContext): (PreparedPlanExecution, TransactionalContextWrapperv3_1) = { + protected def planQuery(transactionalContext: TransactionalContext): (PreparedPlanExecution, TransactionalContextWrapperv3_2) = { val executingQuery = transactionalContext.executingQuery() val queryText = executingQuery.queryText() executionMonitor.startQueryExecution(executingQuery) val phaseTracer = compilationTracer.compileQuery(queryText) try { - val externalTransactionalContext = new TransactionalContextWrapperv3_1(transactionalContext) + val externalTransactionalContext = new TransactionalContextWrapperv3_2(transactionalContext) val preParsedQuery = try { preParseQuery(queryText) } catch { @@ -157,7 +157,7 @@ class ExecutionEngine(val queryService: GraphDatabaseQueryService, logProvider: // fetch plan cache val cache = getOrCreateFromSchemaState(tc.readOperations, { cacheMonitor.cacheFlushDetected(tc.statement) - val lruCache = new LRUCachev3_1[String, (ExecutionPlan, Map[String, Any])](getPlanCacheSize) + val lruCache = new LFUCache[String, (ExecutionPlan, Map[String, Any])](getPlanCacheSize) new QueryCache(cacheAccessor, lruCache) }) @@ -223,7 +223,7 @@ class ExecutionEngine(val queryService: GraphDatabaseQueryService, logProvider: queryService, GraphDatabaseSettings.forbid_exhaustive_shortestpath, GraphDatabaseSettings.forbid_exhaustive_shortestpath.getDefaultValue.toBoolean ) - if (((version != CypherVersion.v2_3) || (version != CypherVersion.v3_0) || (version != CypherVersion.v3_1)) && + if (((version != CypherVersion.v2_3) || (version != CypherVersion.v3_1) || (version != CypherVersion.v3_2)) && (planner == CypherPlanner.greedy || planner == CypherPlanner.idp || planner == CypherPlanner.dp)) { val message = s"Cannot combine configurations: ${GraphDatabaseSettings.cypher_parser_version.name}=${version.name} " + s"with ${GraphDatabaseSettings.cypher_planner.name} = ${planner.name}" diff --git a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/ExecutionPlan.scala b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/ExecutionPlan.scala index 33d5976806214..007400b1cc281 100644 --- a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/ExecutionPlan.scala +++ b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/ExecutionPlan.scala @@ -19,7 +19,7 @@ */ package org.neo4j.cypher.internal -import org.neo4j.cypher.internal.spi.TransactionalContextWrapperv3_1 +import org.neo4j.cypher.internal.spi.TransactionalContextWrapperv3_2 import org.neo4j.graphdb.Transaction import org.neo4j.kernel.api.Statement @@ -27,9 +27,9 @@ final case class TransactionInfo(tx: Transaction, isTopLevelTx: Boolean, stateme trait ExecutionPlan { - def run(transactionalContext: TransactionalContextWrapperv3_1, executionMode: CypherExecutionMode, params: Map[String, Any]): ExecutionResult + def run(transactionalContext: TransactionalContextWrapperv3_2, executionMode: CypherExecutionMode, params: Map[String, Any]): ExecutionResult def isPeriodicCommit: Boolean - def isStale(lastCommittedTxId: LastCommittedTxIdProvider, ctx: TransactionalContextWrapperv3_1): Boolean + def isStale(lastCommittedTxId: LastCommittedTxIdProvider, ctx: TransactionalContextWrapperv3_2): Boolean } diff --git a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/ParsedQuery.scala b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/ParsedQuery.scala index 8eb6d0f6a1e8c..6a60ab64c7f1a 100644 --- a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/ParsedQuery.scala +++ b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/ParsedQuery.scala @@ -20,11 +20,10 @@ package org.neo4j.cypher.internal import org.neo4j.cypher.internal.compiler.v3_2.CompilationPhaseTracer -import org.neo4j.cypher.internal.spi.TransactionalContextWrapperv3_1 -import org.neo4j.kernel.api.Statement +import org.neo4j.cypher.internal.spi.TransactionalContextWrapperv3_2 trait ParsedQuery { def isPeriodicCommit: Boolean - def plan(transactionContext: TransactionalContextWrapperv3_1, tracer: CompilationPhaseTracer): (ExecutionPlan, Map[String, Any]) + def plan(transactionContext: TransactionalContextWrapperv3_2, tracer: CompilationPhaseTracer): (ExecutionPlan, Map[String, Any]) def hasErrors: Boolean } diff --git a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/PlannerCache.scala b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/PlannerCache.scala index e2d5b3014176f..a7aa0d1fb54d9 100644 --- a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/PlannerCache.scala +++ b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/PlannerCache.scala @@ -27,19 +27,20 @@ import org.neo4j.kernel.GraphDatabaseQueryService import org.neo4j.kernel.api.KernelAPI import org.neo4j.kernel.monitoring.{Monitors => KernelMonitors} import org.neo4j.logging.Log +import helpers.wrappersFor2_3._ +import helpers.wrappersFor3_1._ import scala.collection.mutable sealed trait PlannerSpec final case class PlannerSpec_v2_3(planner: CypherPlanner, runtime: CypherRuntime) extends PlannerSpec -final case class PlannerSpec_v3_0(planner: CypherPlanner, runtime: CypherRuntime, updateStrategy: CypherUpdateStrategy) extends PlannerSpec final case class PlannerSpec_v3_1(planner: CypherPlanner, runtime: CypherRuntime, updateStrategy: CypherUpdateStrategy) extends PlannerSpec +final case class PlannerSpec_v3_2(planner: CypherPlanner, runtime: CypherRuntime, updateStrategy: CypherUpdateStrategy) extends PlannerSpec + class PlannerFactory(graph: GraphDatabaseQueryService, kernelAPI: KernelAPI, kernelMonitors: KernelMonitors, log: Log, config: CypherCompilerConfiguration) { - import helpers.wrappersFor2_3._ - import helpers.wrappersFor3_0._ def create(spec: PlannerSpec_v2_3) = spec.planner match { case CypherPlanner.rule => CompatibilityFor2_3Rule(graph, as2_3(config), Clock.SYSTEM_CLOCK, kernelMonitors, kernelAPI) @@ -47,28 +48,30 @@ class PlannerFactory(graph: GraphDatabaseQueryService, kernelAPI: KernelAPI, ker Clock.SYSTEM_CLOCK, kernelMonitors, kernelAPI, log, spec.planner, spec.runtime) } - def create(spec: PlannerSpec_v3_0) = spec.planner match { - case CypherPlanner.rule => CompatibilityFor3_0Rule(graph, as3_0(config),CypherCompiler.CLOCK, kernelMonitors, kernelAPI) - case _ => CompatibilityFor3_0Cost(graph, as3_0(config), - CypherCompiler.CLOCK, kernelMonitors, kernelAPI, log, spec.planner, spec.runtime, spec.updateStrategy) - } - def create(spec: PlannerSpec_v3_1) = spec.planner match { - case CypherPlanner.rule => CompatibilityFor3_1Rule(graph, config, CypherCompiler.CLOCK, kernelMonitors, kernelAPI) - case _ => CompatibilityFor3_1Cost(graph, config, + case CypherPlanner.rule => CompatibilityFor3_1Rule(graph, as3_1(config), CypherCompiler.CLOCK, kernelMonitors, kernelAPI) + case _ => CompatibilityFor3_1Cost(graph, as3_1(config), CypherCompiler.CLOCK, kernelMonitors, kernelAPI, log, spec.planner, spec.runtime, spec.updateStrategy) } + + def create(spec: PlannerSpec_v3_2) = spec.planner match { + case CypherPlanner.rule => CompatibilityFor3_2Rule(graph, config, CypherCompiler.CLOCK, kernelMonitors, kernelAPI) + case _ => CompatibilityFor3_2Cost(graph, config, CypherCompiler.CLOCK, kernelMonitors, kernelAPI, log, spec.planner, + spec.runtime, spec.updateStrategy) + } + } class PlannerCache(factory: PlannerFactory) { private val cache_v2_3 = new mutable.HashMap[PlannerSpec_v2_3, CompatibilityFor2_3] - private val cache_v3_0 = new mutable.HashMap[PlannerSpec_v3_0, CompatibilityFor3_0] private val cache_v3_1 = new mutable.HashMap[PlannerSpec_v3_1, CompatibilityFor3_1] + private val cache_v3_2 = new mutable.HashMap[PlannerSpec_v3_2, CompatibilityFor3_2] def apply(spec: PlannerSpec_v2_3) = cache_v2_3.getOrElseUpdate(spec, factory.create(spec)) - def apply(spec: PlannerSpec_v3_0) = cache_v3_0.getOrElseUpdate(spec, factory.create(spec)) def apply(spec: PlannerSpec_v3_1) = cache_v3_1.getOrElseUpdate(spec, factory.create(spec)) + + def apply(spec: PlannerSpec_v3_2) = cache_v3_2.getOrElseUpdate(spec, factory.create(spec)) } class CachingValue[T]() { diff --git a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/PreparedPlanExecution.scala b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/PreparedPlanExecution.scala index 3c03b06939ad4..dd9f334fd443f 100644 --- a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/PreparedPlanExecution.scala +++ b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/PreparedPlanExecution.scala @@ -19,12 +19,12 @@ */ package org.neo4j.cypher.internal -import org.neo4j.cypher.internal.spi.TransactionalContextWrapperv3_1 +import org.neo4j.cypher.internal.spi.TransactionalContextWrapperv3_2 case class PreparedPlanExecution(plan: ExecutionPlan, executionMode: CypherExecutionMode, extractedParams: Map[String, Any]) { - def execute(transactionalContext: TransactionalContextWrapperv3_1, params: Map[String, Any]): ExecutionResult = + def execute(transactionalContext: TransactionalContextWrapperv3_2, params: Map[String, Any]): ExecutionResult = plan.run(transactionalContext, executionMode, params ++ extractedParams) - def profile(transactionalContext: TransactionalContextWrapperv3_1, params: Map[String, Any]): ExecutionResult = + def profile(transactionalContext: TransactionalContextWrapperv3_2, params: Map[String, Any]): ExecutionResult = plan.run(transactionalContext, CypherExecutionMode.profile, params ++ extractedParams) } diff --git a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/compatibility/CompatibilityFor2_3.scala b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/compatibility/CompatibilityFor2_3.scala index 6c6012c70927f..85d92d5f76038 100644 --- a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/compatibility/CompatibilityFor2_3.scala +++ b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/compatibility/CompatibilityFor2_3.scala @@ -34,7 +34,7 @@ import org.neo4j.cypher.internal.frontend.v2_3.notification.{InternalNotificatio import org.neo4j.cypher.internal.frontend.v2_3.spi.MapToPublicExceptions import org.neo4j.cypher.internal.frontend.v2_3.{CypherException => InternalCypherException, InputPosition => InternalInputPosition} import org.neo4j.cypher.internal.javacompat.{PlanDescription, ProfilerStatistics} -import org.neo4j.cypher.internal.spi.TransactionalContextWrapperv3_1 +import org.neo4j.cypher.internal.spi.TransactionalContextWrapperv3_2 import org.neo4j.cypher.internal.spi.v2_3.{TransactionBoundGraphStatistics, TransactionBoundPlanContext, TransactionBoundQueryContext} import org.neo4j.cypher.internal.{CypherExecutionMode, ExecutionResult, LastCommittedTxIdProvider, ParsedQuery, PreParsedQuery, QueryStatistics} import org.neo4j.cypher.javacompat.internal.GraphDatabaseCypherService @@ -171,7 +171,7 @@ trait CompatibilityFor2_3 { new ParsedQuery { def isPeriodicCommit = preparedQueryForV_2_3.map(_.isPeriodicCommit).getOrElse(false) - def plan(transactionalContext: TransactionalContextWrapperv3_1, tracer: v3_2.CompilationPhaseTracer): (org.neo4j.cypher.internal.ExecutionPlan, Map[String, Any]) = exceptionHandlerFor2_3.runSafely { + def plan(transactionalContext: TransactionalContextWrapperv3_2, tracer: v3_2.CompilationPhaseTracer): (org.neo4j.cypher.internal.ExecutionPlan, Map[String, Any]) = exceptionHandlerFor2_3.runSafely { val planContext: PlanContext = new TransactionBoundPlanContext(transactionalContext) val (planImpl, extractedParameters) = compiler.planPreparedQuery(preparedQueryForV_2_3.get, planContext, as2_3(tracer)) @@ -187,10 +187,10 @@ trait CompatibilityFor2_3 { class ExecutionPlanWrapper(inner: ExecutionPlan_v2_3) extends org.neo4j.cypher.internal.ExecutionPlan { - private def queryContext(transactionalContext: TransactionalContextWrapperv3_1): QueryContext = + private def queryContext(transactionalContext: TransactionalContextWrapperv3_2): QueryContext = new ExceptionTranslatingQueryContextFor2_3(new TransactionBoundQueryContext(transactionalContext)) - def run(transactionalContext: TransactionalContextWrapperv3_1, executionMode: CypherExecutionMode, params: Map[String, Any]): ExecutionResult = { + def run(transactionalContext: TransactionalContextWrapperv3_2, executionMode: CypherExecutionMode, params: Map[String, Any]): ExecutionResult = { val innerExecutionMode = executionMode match { case CypherExecutionMode.explain => ExplainModev2_3 case CypherExecutionMode.profile => ProfileModev2_3 @@ -212,7 +212,7 @@ trait CompatibilityFor2_3 { def isPeriodicCommit = inner.isPeriodicCommit - def isStale(lastCommittedTxId: LastCommittedTxIdProvider, ctx: TransactionalContextWrapperv3_1): Boolean = + def isStale(lastCommittedTxId: LastCommittedTxIdProvider, ctx: TransactionalContextWrapperv3_2): Boolean = inner.isStale(lastCommittedTxId, TransactionBoundGraphStatistics(ctx.readOperations)) } } diff --git a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/compatibility/CompatibilityFor3_1.scala b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/compatibility/CompatibilityFor3_1.scala index 01d326eda99b8..ce56daa729720 100644 --- a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/compatibility/CompatibilityFor3_1.scala +++ b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/compatibility/CompatibilityFor3_1.scala @@ -25,23 +25,24 @@ import java.util.Collections import org.neo4j.cypher._ import org.neo4j.cypher.internal._ -import org.neo4j.cypher.internal.compiler.v3_2 -import org.neo4j.cypher.internal.compiler.v3_2.executionplan.{ExecutionPlan => ExecutionPlan_v3_1, _} -import org.neo4j.cypher.internal.compiler.v3_2.helpers.RuntimeTypeConverter -import org.neo4j.cypher.internal.compiler.v3_2.planDescription.InternalPlanDescription.Arguments._ -import org.neo4j.cypher.internal.compiler.v3_2.planDescription.{Argument, InternalPlanDescription, PlanDescriptionArgumentSerializer} -import org.neo4j.cypher.internal.compiler.v3_2.spi.{InternalResultRow, InternalResultVisitor} -import org.neo4j.cypher.internal.compiler.v3_2.tracing.rewriters.RewriterStepSequencer -import org.neo4j.cypher.internal.compiler.v3_2.{CypherCompilerFactory, DPPlannerName, IDPPlannerName, InfoLogger, Monitors, PlannerName, ExplainMode => ExplainModev3_1, NormalMode => NormalModev3_1, ProfileMode => ProfileModev3_1, _} -import org.neo4j.cypher.internal.frontend.v3_0.helpers.Eagerly -import org.neo4j.cypher.internal.frontend.v3_2.notification.{DeprecatedPlannerNotification, InternalNotification, PlannerUnsupportedNotification, RuntimeUnsupportedNotification, _} -import org.neo4j.cypher.internal.frontend.v3_2.spi.MapToPublicExceptions -import org.neo4j.cypher.internal.frontend.v3_2.{CypherException => InternalCypherException} +import org.neo4j.cypher.internal.compiler.v3_1.executionplan.{ExecutionPlan => ExecutionPlan_v3_1, _} +import org.neo4j.cypher.internal.compiler.v3_1.helpers.RuntimeTypeConverter +import org.neo4j.cypher.internal.compiler.v3_1.planDescription.InternalPlanDescription.Arguments._ +import org.neo4j.cypher.internal.compiler.v3_1.planDescription.{Argument, InternalPlanDescription, PlanDescriptionArgumentSerializer} +import org.neo4j.cypher.internal.compiler.v3_1.spi.{InternalResultRow, InternalResultVisitor} +import org.neo4j.cypher.internal.compiler.v3_1.tracing.rewriters.RewriterStepSequencer +import org.neo4j.cypher.internal.compiler.v3_1.{CompilationPhaseTracer, CypherCompilerFactory, DPPlannerName, IDPPlannerName, InfoLogger, Monitors, PlannerName, ExplainMode => ExplainModev3_1, NormalMode => NormalModev3_1, ProfileMode => ProfileModev3_1, _} +import org.neo4j.cypher.internal.compiler.{v3_1, v3_2} +import org.neo4j.cypher.internal.frontend.v3_1.helpers.Eagerly +import org.neo4j.cypher.internal.frontend.v3_1.notification.{DeprecatedPlannerNotification, InternalNotification, PlannerUnsupportedNotification, RuntimeUnsupportedNotification, _} +import org.neo4j.cypher.internal.frontend.v3_1.spi.MapToPublicExceptions +import org.neo4j.cypher.internal.frontend.v3_1.{CypherException => InternalCypherException} +import org.neo4j.cypher.internal.helpers.wrappersFor3_1._ import org.neo4j.cypher.internal.javacompat.{PlanDescription, ProfilerStatistics} -import org.neo4j.cypher.internal.spi.TransactionalContextWrapperv3_1 import org.neo4j.cypher.internal.spi.v3_1.TransactionBoundQueryContext.IndexSearchMonitor import org.neo4j.cypher.internal.spi.v3_1._ import org.neo4j.cypher.internal.spi.v3_1.codegen.GeneratedQueryStructure +import org.neo4j.cypher.internal.spi.{TransactionalContextWrapperv3_1, TransactionalContextWrapperv3_2} import org.neo4j.graphdb import org.neo4j.graphdb.Result.{ResultRow, ResultVisitor} import org.neo4j.graphdb.impl.notification.{NotificationCode, NotificationDetail} @@ -219,13 +220,13 @@ trait CompatibilityFor3_1 { val kernelAPI: KernelAPI protected val rewriterSequencer: (String) => RewriterStepSequencer = { - import org.neo4j.cypher.internal.compiler.v3_2.tracing.rewriters.RewriterStepSequencer._ + import org.neo4j.cypher.internal.compiler.v3_1.tracing.rewriters.RewriterStepSequencer._ import org.neo4j.helpers.Assertion._ if (assertionsEnabled()) newValidating else newPlain } - protected val compiler: v3_2.CypherCompiler + protected val compiler: v3_1.CypherCompiler implicit val executionMonitor = kernelMonitors.newMonitor(classOf[QueryExecutionMonitor]) @@ -236,20 +237,22 @@ trait CompatibilityFor3_1 { preParsedQuery.rawStatement, notificationLogger, preParsedQuery.planner.name, - Some(preParsedQuery.offset), tracer)) + Some(as3_1(preParsedQuery.offset)), tracer)) new ParsedQuery { def isPeriodicCommit = preparedSyntacticQueryForV_3_1.map(_.isPeriodicCommit).getOrElse(false) - def plan(transactionalContext: TransactionalContextWrapperv3_1, tracer: CompilationPhaseTracer): (ExecutionPlan, Map[String, Any]) = exceptionHandlerFor3_1.runSafely { - val planContext = new ExceptionTranslatingPlanContext(new TransactionBoundPlanContext(transactionalContext, notificationLogger)) - val syntacticQuery = preparedSyntacticQueryForV_3_1.get - val (planImpl, extractedParameters) = compiler.planPreparedQuery(syntacticQuery, notificationLogger, planContext, Some(preParsedQuery.offset), tracer) + def plan(transactionalContext: TransactionalContextWrapperv3_2, tracer: v3_2.CompilationPhaseTracer): (ExecutionPlan, Map[String, Any]) = + exceptionHandlerFor3_1.runSafely { + val tc = TransactionalContextWrapperv3_1(transactionalContext.tc) + val planContext = new ExceptionTranslatingPlanContext(new TransactionBoundPlanContext(tc, notificationLogger)) + val syntacticQuery = preparedSyntacticQueryForV_3_1.get + val (planImpl, extractedParameters) = compiler.planPreparedQuery(syntacticQuery, notificationLogger, planContext, Some(as3_1(preParsedQuery.offset)), as3_1(tracer)) - // Log notifications/warnings from planning - planImpl.notifications(planContext).foreach(notificationLogger += _) + // Log notifications/warnings from planning + planImpl.notifications(planContext).foreach(notificationLogger += _) - (new ExecutionPlanWrapper(planImpl), extractedParameters) - } + (new ExecutionPlanWrapper(planImpl), extractedParameters) + } override def hasErrors = preparedSyntacticQueryForV_3_1.isFailure } @@ -259,12 +262,12 @@ trait CompatibilityFor3_1 { private val searchMonitor = kernelMonitors.newMonitor(classOf[IndexSearchMonitor]) - private def queryContext(transactionalContext: TransactionalContextWrapperv3_1) = { - val ctx = new TransactionBoundQueryContext(transactionalContext)(searchMonitor) + private def queryContext(transactionalContext: TransactionalContextWrapperv3_2) = { + val ctx = new TransactionBoundQueryContext(TransactionalContextWrapperv3_1(transactionalContext.tc))(searchMonitor) new ExceptionTranslatingQueryContextFor3_1(ctx) } - def run(transactionalContext: TransactionalContextWrapperv3_1, executionMode: CypherExecutionMode, params: Map[String, Any]): ExecutionResult = { + def run(transactionalContext: TransactionalContextWrapperv3_2, executionMode: CypherExecutionMode, params: Map[String, Any]): ExecutionResult = { val innerExecutionMode = executionMode match { case CypherExecutionMode.explain => ExplainModev3_1 case CypherExecutionMode.profile => ProfileModev3_1 @@ -283,7 +286,7 @@ trait CompatibilityFor3_1 { def isPeriodicCommit = inner.isPeriodicCommit - def isStale(lastCommittedTxId: LastCommittedTxIdProvider, ctx: TransactionalContextWrapperv3_1): Boolean = + def isStale(lastCommittedTxId: LastCommittedTxIdProvider, ctx: TransactionalContextWrapperv3_2): Boolean = inner.isStale(lastCommittedTxId, TransactionBoundGraphStatistics(ctx.readOperations)) } } @@ -415,7 +418,7 @@ class ExecutionResultWrapperFor3_1(val inner: InternalExecutionResult, val plann override def getString(key: String): String = row.getString(key) } - private implicit class ConvertibleCompilerInputPosition(pos: frontend.v3_2.InputPosition) { + private implicit class ConvertibleCompilerInputPosition(pos: frontend.v3_1.InputPosition) { def asInputPosition = new graphdb.InputPosition(pos.offset, pos.line, pos.column) } } diff --git a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/compatibility/CompatibilityFor3_0.scala b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/compatibility/CompatibilityFor3_2.scala similarity index 67% rename from community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/compatibility/CompatibilityFor3_0.scala rename to community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/compatibility/CompatibilityFor3_2.scala index 7acbad183e497..89bd5d1372f09 100644 --- a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/compatibility/CompatibilityFor3_0.scala +++ b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/compatibility/CompatibilityFor3_2.scala @@ -22,31 +22,30 @@ package org.neo4j.cypher.internal.compatibility import java.io.PrintWriter import java.time.Clock import java.util.Collections -import java.{lang, util} import org.neo4j.cypher._ import org.neo4j.cypher.internal._ -import org.neo4j.cypher.internal.compiler.v3_0.executionplan.{ExecutionPlan => ExecutionPlan_v3_0, _} -import org.neo4j.cypher.internal.compiler.v3_0.helpers.RuntimeTypeConverter -import org.neo4j.cypher.internal.compiler.v3_0.planDescription.InternalPlanDescription.Arguments._ -import org.neo4j.cypher.internal.compiler.v3_0.planDescription.{Argument, InternalPlanDescription, PlanDescriptionArgumentSerializer} -import org.neo4j.cypher.internal.compiler.v3_0.spi.{InternalResultRow, InternalResultVisitor} -import org.neo4j.cypher.internal.compiler.v3_0.tracing.rewriters.RewriterStepSequencer -import org.neo4j.cypher.internal.compiler.v3_0.{CypherCompilerFactory, DPPlannerName, IDPPlannerName, InfoLogger, Monitors, PlannerName, ExplainMode => ExplainModev3_0, NormalMode => NormalModev3_0, ProfileMode => ProfileModev3_0, _} -import org.neo4j.cypher.internal.compiler.v3_2.{CRS, Coordinate, Geometry, Point} -import org.neo4j.cypher.internal.compiler.{v3_0, v3_2} -import org.neo4j.cypher.internal.frontend.v3_0.helpers.Eagerly -import org.neo4j.cypher.internal.frontend.v3_0.notification.{InternalNotification, PlannerUnsupportedNotification, RuntimeUnsupportedNotification, _} -import org.neo4j.cypher.internal.frontend.v3_0.spi.MapToPublicExceptions -import org.neo4j.cypher.internal.frontend.v3_0.{CypherException => InternalCypherException} -import org.neo4j.cypher.internal.helpers.wrappersFor3_0.as3_0 +import org.neo4j.cypher.internal.compiler.v3_2 +import org.neo4j.cypher.internal.compiler.v3_2.executionplan.{ExecutionPlan => ExecutionPlan_v3_2, _} +import org.neo4j.cypher.internal.compiler.v3_2.helpers.RuntimeTypeConverter +import org.neo4j.cypher.internal.compiler.v3_2.planDescription.InternalPlanDescription.Arguments._ +import org.neo4j.cypher.internal.compiler.v3_2.planDescription.{Argument, InternalPlanDescription, PlanDescriptionArgumentSerializer} +import org.neo4j.cypher.internal.compiler.v3_2.spi.{InternalResultRow, InternalResultVisitor} +import org.neo4j.cypher.internal.compiler.v3_2.tracing.rewriters.RewriterStepSequencer +import org.neo4j.cypher.internal.compiler.v3_2.{CypherCompilerFactory, DPPlannerName, IDPPlannerName, InfoLogger, Monitors, PlannerName, ExplainMode => ExplainModev3_2, NormalMode => NormalModev3_2, ProfileMode => ProfileModev3_2, _} +import org.neo4j.cypher.internal.frontend.v3_2.helpers.Eagerly +import org.neo4j.cypher.internal.frontend.v3_2.notification.{DeprecatedPlannerNotification, InternalNotification, PlannerUnsupportedNotification, RuntimeUnsupportedNotification, _} +import org.neo4j.cypher.internal.frontend.v3_2.spi.MapToPublicExceptions +import org.neo4j.cypher.internal.frontend.v3_2.{CypherException => InternalCypherException} import org.neo4j.cypher.internal.javacompat.{PlanDescription, ProfilerStatistics} -import org.neo4j.cypher.internal.spi.v3_0.TransactionBoundQueryContext.IndexSearchMonitor -import org.neo4j.cypher.internal.spi.v3_0._ -import org.neo4j.cypher.internal.spi.{TransactionalContextWrapperv3_0, TransactionalContextWrapperv3_1} +import org.neo4j.cypher.internal.spi.TransactionalContextWrapperv3_2 +import org.neo4j.cypher.internal.spi.v3_2.TransactionBoundQueryContext.IndexSearchMonitor +import org.neo4j.cypher.internal.spi.v3_2._ +import org.neo4j.cypher.internal.spi.v3_2.codegen.GeneratedQueryStructure +import org.neo4j.graphdb import org.neo4j.graphdb.Result.{ResultRow, ResultVisitor} -import org.neo4j.graphdb._ import org.neo4j.graphdb.impl.notification.{NotificationCode, NotificationDetail} +import org.neo4j.graphdb.spatial import org.neo4j.kernel.GraphDatabaseQueryService import org.neo4j.kernel.api.KernelAPI import org.neo4j.kernel.impl.query.{QueryExecutionMonitor, TransactionalContext} @@ -57,13 +56,13 @@ import scala.collection.JavaConverters._ import scala.reflect.ClassTag import scala.util.Try -object helpersv3_0 { +object helpersv3_2 { implicit def monitorFailure(t: Throwable)(implicit monitor: QueryExecutionMonitor, tc: TransactionalContext): Unit = { monitor.endFailure(tc.executingQuery(), t) } } -object typeConversionsFor3_0 extends RuntimeTypeConverter { +object typeConversionsFor3_2 extends RuntimeTypeConverter { override def asPublicType = { case point: Point => asPublicPoint(point) case geometry: Geometry => asPublicGeometry(geometry) @@ -120,7 +119,7 @@ object typeConversionsFor3_0 extends RuntimeTypeConverter { } private def asPrivateCoordinate(coordinate: spatial.Coordinate) = - Coordinate(coordinate.getCoordinate.asScala.map(_.doubleValue()):_*) + Coordinate(coordinate.getCoordinate.asScala.map(v=>v.doubleValue()):_*) private def asPrivateGeometry(geometry: spatial.Geometry) = new Geometry { override def coordinates: Array[Coordinate] = geometry.getCoordinates.asScala.toArray.map(asPrivateCoordinate) @@ -131,8 +130,7 @@ object typeConversionsFor3_0 extends RuntimeTypeConverter { } } - -object exceptionHandlerFor3_0 extends MapToPublicExceptions[CypherException] { +object exceptionHandlerFor3_2 extends MapToPublicExceptions[CypherException] { def syntaxException(message: String, query: String, offset: Option[Int], cause: Throwable) = new SyntaxException(message, query, offset, cause) def arithmeticException(message: String, cause: Throwable) = new ArithmeticException(message, cause) @@ -153,7 +151,7 @@ object exceptionHandlerFor3_0 extends MapToPublicExceptions[CypherException] { def internalException(message: String, cause: Exception) = new InternalException(message, cause) def loadCsvStatusWrapCypherException(extraInfo: String, cause: InternalCypherException) = - new LoadCsvStatusWrapCypherException(extraInfo, cause.mapToPublic(exceptionHandlerFor3_0)) + new LoadCsvStatusWrapCypherException(extraInfo, cause.mapToPublic(exceptionHandlerFor3_2)) def loadExternalResourceException(message: String, cause: Throwable) = throw new LoadExternalResourceException(message, cause) @@ -187,14 +185,14 @@ object exceptionHandlerFor3_0 extends MapToPublicExceptions[CypherException] { def failedIndexException(indexName: String, cause: Throwable): CypherException = throw new FailedIndexException(indexName, cause) object runSafely extends RunSafely { - override def apply[T](body: => T)(implicit f: Throwable => Unit = (_) => ()) = { + override def apply[T](body: => T)(implicit f: ExceptionHandler = ExceptionHandler.default) = { try { body } catch { case e: InternalCypherException => f(e) - throw e.mapToPublic(exceptionHandlerFor3_0) + throw e.mapToPublic(exceptionHandlerFor3_2) case e: Throwable => f(e) throw e @@ -203,7 +201,7 @@ object exceptionHandlerFor3_0 extends MapToPublicExceptions[CypherException] { } } -case class WrappedMonitors3_0(kernelMonitors: KernelMonitors) extends Monitors { +case class WrappedMonitors3_2(kernelMonitors: KernelMonitors) extends Monitors { def addMonitorListener[T](monitor: T, tags: String*) { kernelMonitors.addMonitorListener(monitor, tags: _*) } @@ -214,38 +212,38 @@ case class WrappedMonitors3_0(kernelMonitors: KernelMonitors) extends Monitors { } } -trait CompatibilityFor3_0 { +trait CompatibilityFor3_2 { val graph: GraphDatabaseQueryService val queryCacheSize: Int val kernelMonitors: KernelMonitors val kernelAPI: KernelAPI protected val rewriterSequencer: (String) => RewriterStepSequencer = { - import org.neo4j.cypher.internal.compiler.v3_0.tracing.rewriters.RewriterStepSequencer._ + import org.neo4j.cypher.internal.compiler.v3_2.tracing.rewriters.RewriterStepSequencer._ import org.neo4j.helpers.Assertion._ if (assertionsEnabled()) newValidating else newPlain } - protected val compiler: v3_0.CypherCompiler + protected val compiler: v3_2.CypherCompiler implicit val executionMonitor = kernelMonitors.newMonitor(classOf[QueryExecutionMonitor]) def produceParsedQuery(preParsedQuery: PreParsedQuery, tracer: CompilationPhaseTracer) = { val notificationLogger = new RecordingNotificationLogger - val preparedSyntacticQueryForV_3_0 = + val preparedSyntacticQueryForV_3_2 = Try(compiler.prepareSyntacticQuery(preParsedQuery.statement, preParsedQuery.rawStatement, notificationLogger, preParsedQuery.planner.name, - Some(as3_0(preParsedQuery.offset)), tracer)) + Some(preParsedQuery.offset), tracer)) new ParsedQuery { - def isPeriodicCommit = preparedSyntacticQueryForV_3_0.map(_.isPeriodicCommit).getOrElse(false) + def isPeriodicCommit = preparedSyntacticQueryForV_3_2.map(_.isPeriodicCommit).getOrElse(false) - def plan(transactionalContext: TransactionalContextWrapperv3_1, tracer: v3_2.CompilationPhaseTracer): (ExecutionPlan, Map[String, Any]) = exceptionHandlerFor3_0.runSafely { - val planContext = new ExceptionTranslatingPlanContext(new TransactionBoundPlanContext(transactionalContext)) - val syntacticQuery = preparedSyntacticQueryForV_3_0.get - val (planImpl, extractedParameters) = compiler.planPreparedQuery(syntacticQuery, planContext, Some(as3_0(preParsedQuery.offset)), as3_0(tracer)) + def plan(transactionalContext: TransactionalContextWrapperv3_2, tracer: CompilationPhaseTracer): (ExecutionPlan, Map[String, Any]) = exceptionHandlerFor3_2.runSafely { + val planContext = new ExceptionTranslatingPlanContext(new TransactionBoundPlanContext(transactionalContext, notificationLogger)) + val syntacticQuery = preparedSyntacticQueryForV_3_2.get + val (planImpl, extractedParameters) = compiler.planPreparedQuery(syntacticQuery, notificationLogger, planContext, Some(preParsedQuery.offset), tracer) // Log notifications/warnings from planning planImpl.notifications(planContext).foreach(notificationLogger += _) @@ -253,54 +251,52 @@ trait CompatibilityFor3_0 { (new ExecutionPlanWrapper(planImpl), extractedParameters) } - override def hasErrors = preparedSyntacticQueryForV_3_0.isFailure + override def hasErrors = preparedSyntacticQueryForV_3_2.isFailure } } - class ExecutionPlanWrapper(inner: ExecutionPlan_v3_0) extends ExecutionPlan { - val searchMonitor = kernelMonitors.newMonitor(classOf[IndexSearchMonitor]) + class ExecutionPlanWrapper(inner: ExecutionPlan_v3_2) extends ExecutionPlan { + + private val searchMonitor = kernelMonitors.newMonitor(classOf[IndexSearchMonitor]) - private def queryContext(transactionalContext: TransactionalContextWrapperv3_0) = { + private def queryContext(transactionalContext: TransactionalContextWrapperv3_2) = { val ctx = new TransactionBoundQueryContext(transactionalContext)(searchMonitor) - new ExceptionTranslatingQueryContextFor3_0(ctx) + new ExceptionTranslatingQueryContextFor3_2(ctx) } - def run(transactionalContext: TransactionalContextWrapperv3_1, executionMode: CypherExecutionMode, params: Map[String, Any]): ExecutionResult = { + def run(transactionalContext: TransactionalContextWrapperv3_2, executionMode: CypherExecutionMode, params: Map[String, Any]): ExecutionResult = { val innerExecutionMode = executionMode match { - case CypherExecutionMode.explain => ExplainModev3_0 - case CypherExecutionMode.profile => ProfileModev3_0 - case CypherExecutionMode.normal => NormalModev3_0 + case CypherExecutionMode.explain => ExplainModev3_2 + case CypherExecutionMode.profile => ProfileModev3_2 + case CypherExecutionMode.normal => NormalModev3_2 } - exceptionHandlerFor3_0.runSafely { - val innerParams = typeConversionsFor3_1.asPrivateMap(params) - - val innerResult = inner.run(queryContext(TransactionalContextWrapperv3_0(transactionalContext.tc)), innerExecutionMode, innerParams) + exceptionHandlerFor3_2.runSafely { + val innerParams = typeConversionsFor3_2.asPrivateMap(params) + val innerResult = inner.run(queryContext(transactionalContext), innerExecutionMode, innerParams) new ClosingExecutionResult( transactionalContext.tc.executingQuery(), - ExecutionResultWrapperFor3_0(innerResult, inner.plannerUsed, inner.runtimeUsed), - exceptionHandlerFor3_0.runSafely + new ExecutionResultWrapperFor3_2(innerResult, inner.plannerUsed, inner.runtimeUsed), + exceptionHandlerFor3_2.runSafely ) } } def isPeriodicCommit = inner.isPeriodicCommit - def isStale(lastCommittedTxId: LastCommittedTxIdProvider, ctx: TransactionalContextWrapperv3_1): Boolean = + def isStale(lastCommittedTxId: LastCommittedTxIdProvider, ctx: TransactionalContextWrapperv3_2): Boolean = inner.isStale(lastCommittedTxId, TransactionBoundGraphStatistics(ctx.readOperations)) } - } -object ExecutionResultWrapperFor3_0 { +object ExecutionResultWrapperFor3_2 { def unapply(v: Any): Option[(InternalExecutionResult, PlannerName, RuntimeName)] = v match { case closing: ClosingExecutionResult => unapply(closing.inner) - case wrapper: ExecutionResultWrapperFor3_0 => Some((wrapper.inner, wrapper.planner, wrapper.runtime)) + case wrapper: ExecutionResultWrapperFor3_2 => Some((wrapper.inner, wrapper.planner, wrapper.runtime)) case _ => None } } -case class ExecutionResultWrapperFor3_0(inner: InternalExecutionResult, planner: PlannerName, runtime: RuntimeName) - (implicit innerMonitor: QueryExecutionMonitor) +class ExecutionResultWrapperFor3_2(val inner: InternalExecutionResult, val planner: PlannerName, val runtime: RuntimeName) extends ExecutionResult { override def planDescriptionRequested = inner.planDescriptionRequested @@ -309,10 +305,9 @@ case class ExecutionResultWrapperFor3_0(inner: InternalExecutionResult, planner: override def columns = inner.columns override def javaColumns = inner.javaColumns - - def queryStatistics() = exceptionHandlerFor3_0.runSafely { + override def queryStatistics() = { val i = inner.queryStatistics() - org.neo4j.cypher.internal.QueryStatistics(nodesCreated = i.nodesCreated, + QueryStatistics(nodesCreated = i.nodesCreated, relationshipsCreated = i.relationshipsCreated, propertiesSet = i.propertiesSet, nodesDeleted = i.nodesDeleted, @@ -331,38 +326,35 @@ case class ExecutionResultWrapperFor3_0(inner: InternalExecutionResult, planner: override def javaColumnAs[T](column: String) = inner.javaColumnAs(column) - def executionPlanDescription(): org.neo4j.cypher.internal.PlanDescription = - exceptionHandlerFor3_0.runSafely { - convert( - inner.executionPlanDescription(). - addArgument(Version("CYPHER 3.0")). - addArgument(Planner(planner.toTextOutput)). - addArgument(PlannerImpl(planner.name)). - addArgument(Runtime(runtime.toTextOutput)). - addArgument(RuntimeImpl(runtime.name)) + override def executionPlanDescription(): org.neo4j.cypher.internal.PlanDescription = + convert( + inner.executionPlanDescription(). + addArgument(Version("CYPHER 3.2")). + addArgument(Planner(planner.toTextOutput)). + addArgument(PlannerImpl(planner.name)). + addArgument(Runtime(runtime.toTextOutput)). + addArgument(RuntimeImpl(runtime.name)) ) - } - private def convert(i: InternalPlanDescription): org.neo4j.cypher.internal.PlanDescription = exceptionHandlerFor3_0.runSafely { - CompatibilityPlanDescriptionFor3_0(i, CypherVersion.v3_0, planner, runtime) - } + private def convert(i: InternalPlanDescription): org.neo4j.cypher.internal.PlanDescription = + CompatibilityPlanDescriptionFor3_2(i, CypherVersion.v3_2, planner, runtime) override def hasNext = inner.hasNext override def next() = inner.next() override def close() = inner.close() - def executionType: QueryExecutionType = { + override def executionType: graphdb.QueryExecutionType = { val qt = inner.executionType match { - case READ_ONLY => QueryExecutionType.QueryType.READ_ONLY - case READ_WRITE => QueryExecutionType.QueryType.READ_WRITE - case WRITE => QueryExecutionType.QueryType.WRITE - case SCHEMA_WRITE => QueryExecutionType.QueryType.SCHEMA_WRITE - case DBMS => QueryExecutionType.QueryType.READ_ONLY // TODO: We need to decide how we expose this in the public API + case READ_ONLY => graphdb.QueryExecutionType.QueryType.READ_ONLY + case READ_WRITE => graphdb.QueryExecutionType.QueryType.READ_WRITE + case WRITE => graphdb.QueryExecutionType.QueryType.WRITE + case SCHEMA_WRITE => graphdb.QueryExecutionType.QueryType.SCHEMA_WRITE + case DBMS => graphdb.QueryExecutionType.QueryType.READ_ONLY // TODO: We need to decide how we expose this in the public API } inner.executionMode match { - case ExplainModev3_0 => QueryExecutionType.explained(qt) - case ProfileModev3_0 => QueryExecutionType.profiled(qt) - case NormalModev3_0 => QueryExecutionType.query(qt) + case ExplainModev3_2 => graphdb.QueryExecutionType.explained(qt) + case ProfileModev3_2 => graphdb.QueryExecutionType.profiled(qt) + case NormalModev3_2 => graphdb.QueryExecutionType.query(qt) } } @@ -374,21 +366,21 @@ case class ExecutionResultWrapperFor3_0(inner: InternalExecutionResult, planner: case LengthOnNonPathNotification(pos) => NotificationCode.LENGTH_ON_NON_PATH.notification(pos.asInputPosition) case PlannerUnsupportedNotification => - NotificationCode.PLANNER_UNSUPPORTED.notification(InputPosition.empty) + NotificationCode.PLANNER_UNSUPPORTED.notification(graphdb.InputPosition.empty) case RuntimeUnsupportedNotification => - NotificationCode.RUNTIME_UNSUPPORTED.notification(InputPosition.empty) + NotificationCode.RUNTIME_UNSUPPORTED.notification(graphdb.InputPosition.empty) case IndexHintUnfulfillableNotification(label, propertyKey) => - NotificationCode.INDEX_HINT_UNFULFILLABLE.notification(InputPosition.empty, NotificationDetail.Factory.index(label, propertyKey)) + NotificationCode.INDEX_HINT_UNFULFILLABLE.notification(graphdb.InputPosition.empty, NotificationDetail.Factory.index(label, propertyKey)) case JoinHintUnfulfillableNotification(variables) => - NotificationCode.JOIN_HINT_UNFULFILLABLE.notification(InputPosition.empty, NotificationDetail.Factory.joinKey(variables.asJava)) + NotificationCode.JOIN_HINT_UNFULFILLABLE.notification(graphdb.InputPosition.empty, NotificationDetail.Factory.joinKey(variables.asJava)) case JoinHintUnsupportedNotification(variables) => - NotificationCode.JOIN_HINT_UNSUPPORTED.notification(InputPosition.empty, NotificationDetail.Factory.joinKey(variables.asJava)) + NotificationCode.JOIN_HINT_UNSUPPORTED.notification(graphdb.InputPosition.empty, NotificationDetail.Factory.joinKey(variables.asJava)) case IndexLookupUnfulfillableNotification(labels) => - NotificationCode.INDEX_LOOKUP_FOR_DYNAMIC_PROPERTY.notification(InputPosition.empty, NotificationDetail.Factory.indexSeekOrScan(labels.asJava)) + NotificationCode.INDEX_LOOKUP_FOR_DYNAMIC_PROPERTY.notification(graphdb.InputPosition.empty, NotificationDetail.Factory.indexSeekOrScan(labels.asJava)) case EagerLoadCsvNotification => - NotificationCode.EAGER_LOAD_CSV.notification(InputPosition.empty) + NotificationCode.EAGER_LOAD_CSV.notification(graphdb.InputPosition.empty) case LargeLabelWithLoadCsvNotification => - NotificationCode.LARGE_LABEL_LOAD_CSV.notification(InputPosition.empty) + NotificationCode.LARGE_LABEL_LOAD_CSV.notification(graphdb.InputPosition.empty) case MissingLabelNotification(pos, label) => NotificationCode.MISSING_LABEL.notification(pos.asInputPosition, NotificationDetail.Factory.label(label)) case MissingRelTypeNotification(pos, relType) => @@ -399,6 +391,12 @@ case class ExecutionResultWrapperFor3_0(inner: InternalExecutionResult, planner: NotificationCode.UNBOUNDED_SHORTEST_PATH.notification(pos.asInputPosition) case ExhaustiveShortestPathForbiddenNotification(pos) => NotificationCode.EXHAUSTIVE_SHORTEST_PATH.notification(pos.asInputPosition) + case DeprecatedFunctionNotification(pos, oldName, newName) => + NotificationCode.DEPRECATED_FUNCTION.notification(pos.asInputPosition, NotificationDetail.Factory.deprecatedName(oldName, newName)) + case DeprecatedProcedureNotification(pos, oldName, newName) => + NotificationCode.DEPRECATED_PROCEDURE.notification(pos.asInputPosition, NotificationDetail.Factory.deprecatedName(oldName, newName)) + case DeprecatedPlannerNotification => + NotificationCode.DEPRECATED_PLANNER.notification(graphdb.InputPosition.empty) } override def accept[EX <: Exception](visitor: ResultVisitor[EX]) = inner.accept(wrapVisitor(visitor)) @@ -408,54 +406,53 @@ case class ExecutionResultWrapperFor3_0(inner: InternalExecutionResult, planner: } private def unwrapResultRow(row: InternalResultRow): ResultRow = new ResultRow { - override def getRelationship(key: String): Relationship = row.getRelationship(key) + override def getRelationship(key: String): graphdb.Relationship = row.getRelationship(key) override def get(key: String): AnyRef = row.get(key) - override def getBoolean(key: String): lang.Boolean = row.getBoolean(key) - override def getPath(key: String): Path = row.getPath(key) - override def getNode(key: String): Node = row.getNode(key) + override def getBoolean(key: String): java.lang.Boolean = row.getBoolean(key) + override def getPath(key: String): graphdb.Path = row.getPath(key) + override def getNode(key: String): graphdb.Node = row.getNode(key) override def getNumber(key: String): Number = row.getNumber(key) override def getString(key: String): String = row.getString(key) } - private implicit class ConvertibleCompilerInputPosition(pos: frontend.v3_0.InputPosition) { - def asInputPosition = new InputPosition(pos.offset, pos.line, pos.column) + private implicit class ConvertibleCompilerInputPosition(pos: frontend.v3_2.InputPosition) { + def asInputPosition = new graphdb.InputPosition(pos.offset, pos.line, pos.column) } - } -case class CompatibilityPlanDescriptionFor3_0(inner: InternalPlanDescription, version: CypherVersion, +case class CompatibilityPlanDescriptionFor3_2(inner: InternalPlanDescription, version: CypherVersion, planner: PlannerName, runtime: RuntimeName) extends org.neo4j.cypher.internal.PlanDescription { self => - def children = exceptionHandlerFor3_0.runSafely { - inner.children.toSeq.map(CompatibilityPlanDescriptionFor3_0.apply(_, version, planner, runtime)) + def children = exceptionHandlerFor3_2.runSafely { + inner.children.toIndexedSeq.map(CompatibilityPlanDescriptionFor3_2.apply(_, version, planner, runtime)) } - def arguments: Map[String, AnyRef] = exceptionHandlerFor3_0.runSafely { + def arguments: Map[String, AnyRef] = exceptionHandlerFor3_2.runSafely { inner.arguments.map { arg => arg.name -> PlanDescriptionArgumentSerializer.serialize(arg) }.toMap } - def identifiers = exceptionHandlerFor3_0.runSafely { + def identifiers = exceptionHandlerFor3_2.runSafely { inner.orderedVariables.toSet } - override def hasProfilerStatistics = exceptionHandlerFor3_0.runSafely { + override def hasProfilerStatistics = exceptionHandlerFor3_2.runSafely { inner.arguments.exists(_.isInstanceOf[DbHits]) } - def name = exceptionHandlerFor3_0.runSafely { + def name = exceptionHandlerFor3_2.runSafely { inner.name } - def asJava: PlanDescription = exceptionHandlerFor3_0.runSafely { + def asJava: PlanDescription = exceptionHandlerFor3_2.runSafely { asJava(self) } override def toString: String = { val NL = System.lineSeparator() - exceptionHandlerFor3_0.runSafely { + exceptionHandlerFor3_2.runSafely { s"Compiler CYPHER ${version.name}$NL${NL}Planner ${planner.toTextOutput.toUpperCase}$NL${NL}Runtime ${runtime.toTextOutput.toUpperCase}$NL$NL$inner" } } @@ -474,23 +471,23 @@ case class CompatibilityPlanDescriptionFor3_0(inner: InternalPlanDescription, ve def hasProfilerStatistics: Boolean = self.hasProfilerStatistics - def getArguments: util.Map[String, AnyRef] = arguments.asJava + def getArguments: java.util.Map[String, AnyRef] = arguments.asJava - def getIdentifiers: util.Set[String] = identifiers.asJava + def getIdentifiers: java.util.Set[String] = identifiers.asJava - def getChildren: util.List[PlanDescription] = in.children.toList.map(_.asJava).asJava + def getChildren: java.util.List[PlanDescription] = in.children.toList.map(_.asJava).asJava override def toString: String = self.toString } } -class StringInfoLogger3_0(log: Log) extends InfoLogger { +class StringInfoLogger3_2(log: Log) extends InfoLogger { def info(message: String) { log.info(message) } } -case class CompatibilityFor3_0Cost(graph: GraphDatabaseQueryService, +case class CompatibilityFor3_2Cost(graph: GraphDatabaseQueryService, config: CypherCompilerConfiguration, clock: Clock, kernelMonitors: KernelMonitors, @@ -498,7 +495,7 @@ case class CompatibilityFor3_0Cost(graph: GraphDatabaseQueryService, log: Log, planner: CypherPlanner, runtime: CypherRuntime, - strategy: CypherUpdateStrategy) extends CompatibilityFor3_0 { + strategy: CypherUpdateStrategy) extends CompatibilityFor3_2 { protected val compiler = { val plannerName = planner match { @@ -511,30 +508,30 @@ case class CompatibilityFor3_0Cost(graph: GraphDatabaseQueryService, val runtimeName = runtime match { case CypherRuntime.default => None case CypherRuntime.interpreted => Some(InterpretedRuntimeName) - case CypherRuntime.compiled => throw new IllegalArgumentException("Compiled runtime is not supported in 3.0") + case CypherRuntime.compiled => Some(CompiledRuntimeName) } val updateStrategy = strategy match { case CypherUpdateStrategy.eager => Some(eagerUpdateStrategy) case _ => None } - val logger = new StringInfoLogger3_0(log) - val monitors = WrappedMonitors3_0(kernelMonitors) - CypherCompilerFactory.costBasedCompiler(graph, config, clock, monitors, logger, - rewriterSequencer, plannerName, runtimeName, updateStrategy, typeConversionsFor3_0) + val logger = new StringInfoLogger3_2(log) + val monitors = WrappedMonitors3_2(kernelMonitors) + CypherCompilerFactory.costBasedCompiler(graph, config, clock, GeneratedQueryStructure, monitors, logger, + rewriterSequencer, plannerName, runtimeName, updateStrategy, typeConversionsFor3_2) } override val queryCacheSize: Int = config.queryCacheSize } -case class CompatibilityFor3_0Rule(graph: GraphDatabaseQueryService, +case class CompatibilityFor3_2Rule(graph: GraphDatabaseQueryService, config: CypherCompilerConfiguration, clock: Clock, kernelMonitors: KernelMonitors, - kernelAPI: KernelAPI) extends CompatibilityFor3_0 { + kernelAPI: KernelAPI) extends CompatibilityFor3_2 { protected val compiler = { - val monitors = WrappedMonitors3_0(kernelMonitors) - CypherCompilerFactory.ruleBasedCompiler(graph, config, clock, monitors, rewriterSequencer, typeConversionsFor3_0) + val monitors = WrappedMonitors3_2(kernelMonitors) + CypherCompilerFactory.ruleBasedCompiler(graph, config, clock, monitors, rewriterSequencer, typeConversionsFor3_2) } override val queryCacheSize: Int = config.queryCacheSize diff --git a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/compatibility/ExceptionTranslatingQueryContextFor3_1.scala b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/compatibility/ExceptionTranslatingQueryContextFor3_1.scala index c45beab1f698b..6edf53a57f5ae 100644 --- a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/compatibility/ExceptionTranslatingQueryContextFor3_1.scala +++ b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/compatibility/ExceptionTranslatingQueryContextFor3_1.scala @@ -21,10 +21,10 @@ package org.neo4j.cypher.internal.compatibility import java.net.URL -import org.neo4j.cypher.internal.compiler.v3_2.commands.expressions.{Expander, KernelPredicate} -import org.neo4j.cypher.internal.compiler.v3_2.pipes.matching.PatternNode -import org.neo4j.cypher.internal.compiler.v3_2.spi._ -import org.neo4j.cypher.internal.frontend.v3_2.SemanticDirection +import org.neo4j.cypher.internal.compiler.v3_1.commands.expressions.{Expander, KernelPredicate} +import org.neo4j.cypher.internal.compiler.v3_1.pipes.matching.PatternNode +import org.neo4j.cypher.internal.compiler.v3_1.spi._ +import org.neo4j.cypher.internal.frontend.v3_1.SemanticDirection import org.neo4j.cypher.internal.spi.v3_1.ExceptionTranslationSupport import org.neo4j.graphdb.{Node, Path, PropertyContainer, Relationship} import org.neo4j.kernel.api.index.IndexDescriptor diff --git a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/compatibility/ExceptionTranslatingQueryContextFor3_0.scala b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/compatibility/ExceptionTranslatingQueryContextFor3_2.scala similarity index 87% rename from community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/compatibility/ExceptionTranslatingQueryContextFor3_0.scala rename to community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/compatibility/ExceptionTranslatingQueryContextFor3_2.scala index e0136f9937c72..81cc97c647418 100644 --- a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/compatibility/ExceptionTranslatingQueryContextFor3_0.scala +++ b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/compatibility/ExceptionTranslatingQueryContextFor3_2.scala @@ -21,17 +21,17 @@ package org.neo4j.cypher.internal.compatibility import java.net.URL -import org.neo4j.cypher.internal.compiler.v3_0.commands.expressions.{Expander, KernelPredicate} -import org.neo4j.cypher.internal.compiler.v3_0.pipes.matching.PatternNode -import org.neo4j.cypher.internal.compiler.v3_0.spi._ -import org.neo4j.cypher.internal.frontend.v3_0.SemanticDirection -import org.neo4j.cypher.internal.spi.v3_0.ExceptionTranslationSupport +import org.neo4j.cypher.internal.compiler.v3_2.commands.expressions.{Expander, KernelPredicate} +import org.neo4j.cypher.internal.compiler.v3_2.pipes.matching.PatternNode +import org.neo4j.cypher.internal.compiler.v3_2.spi._ +import org.neo4j.cypher.internal.frontend.v3_2.SemanticDirection +import org.neo4j.cypher.internal.spi.v3_2.ExceptionTranslationSupport import org.neo4j.graphdb.{Node, Path, PropertyContainer, Relationship} import org.neo4j.kernel.api.index.IndexDescriptor import scala.collection.Iterator -class ExceptionTranslatingQueryContextFor3_0(val inner: QueryContext) extends QueryContext with ExceptionTranslationSupport { +class ExceptionTranslatingQueryContextFor3_2(val inner: QueryContext) extends QueryContext with ExceptionTranslationSupport { override type EntityAccessor = inner.EntityAccessor override def entityAccessor = inner.entityAccessor @@ -129,14 +129,20 @@ class ExceptionTranslatingQueryContextFor3_0(val inner: QueryContext) extends Qu override def dropRelationshipPropertyExistenceConstraint(relTypeId: Int, propertyKeyId: Int) = translateException(inner.dropRelationshipPropertyExistenceConstraint(relTypeId, propertyKeyId)) - override def callReadOnlyProcedure(name: QualifiedProcedureName, args: Seq[Any]): Iterator[Array[AnyRef]] = - translateIterator(inner.callReadOnlyProcedure(name, args)) + override def callReadOnlyProcedure(name: QualifiedName, args: Seq[Any], allowed: Array[String]): Iterator[Array[AnyRef]] = + translateIterator(inner.callReadOnlyProcedure(name, args, allowed)) - override def callReadWriteProcedure(name: QualifiedProcedureName, args: Seq[Any]): Iterator[Array[AnyRef]] = - translateIterator(inner.callReadWriteProcedure(name, args)) + override def callReadWriteProcedure(name: QualifiedName, args: Seq[Any], allowed: Array[String]): Iterator[Array[AnyRef]] = + translateIterator(inner.callReadWriteProcedure(name, args, allowed)) - override def callDbmsProcedure(name: QualifiedProcedureName, args: Seq[Any]): Iterator[Array[AnyRef]] = - translateIterator(inner.callDbmsProcedure(name, args)) + override def callSchemaWriteProcedure(name: QualifiedName, args: Seq[Any], allowed: Array[String]): Iterator[Array[AnyRef]] = + translateIterator(inner.callSchemaWriteProcedure(name, args, allowed)) + + override def callDbmsProcedure(name: QualifiedName, args: Seq[Any], allowed: Array[String]): Iterator[Array[AnyRef]] = + translateIterator(inner.callDbmsProcedure(name, args, allowed)) + + override def callFunction(name: QualifiedName, args: Seq[Any], allowed: Array[String]) = + translateException(inner.callFunction(name, args, allowed)) override def isGraphKernelResultValue(v: Any): Boolean = translateException(inner.isGraphKernelResultValue(v)) @@ -144,7 +150,7 @@ class ExceptionTranslatingQueryContextFor3_0(val inner: QueryContext) extends Qu override def withAnyOpenQueryContext[T](work: (QueryContext) => T): T = inner.withAnyOpenQueryContext(qc => translateException( - work(new ExceptionTranslatingQueryContextFor3_0(qc)) + work(new ExceptionTranslatingQueryContextFor3_2(qc)) )) override def isLabelSetOnNode(label: Int, node: Long): Boolean = @@ -216,9 +222,11 @@ class ExceptionTranslatingQueryContextFor3_0(val inner: QueryContext) extends Qu override def getOptRelTypeId(relType: String) = translateException(inner.getOptRelTypeId(relType)) - override def detachDeleteNode(node: Node) = + override def detachDeleteNode(node: Node): Int = translateException(inner.detachDeleteNode(node)) + override def assertSchemaWritesAllowed(): Unit = translateException(inner.assertSchemaWritesAllowed()) + class ExceptionTranslatingOperations[T <: PropertyContainer](inner: Operations[T]) extends DelegatingOperations[T](inner) { override def delete(obj: T) = diff --git a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/helpers/wrappersFor3_0.scala b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/helpers/wrappersFor3_0.scala deleted file mode 100644 index ec2f248acdf53..0000000000000 --- a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/helpers/wrappersFor3_0.scala +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2002-2016 "Neo Technology," - * Network Engine for Objects in Lund AB [http://neotechnology.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.cypher.internal.helpers - -import org.neo4j.cypher.InternalException -import org.neo4j.cypher.internal.compiler.v3_0 -import org.neo4j.cypher.internal.compiler.v3_0.CompilationPhaseTracer.CompilationPhaseEvent -import org.neo4j.cypher.internal.compiler.v3_0.{CypherCompilerConfiguration => CypherCompilerConfiguration3_0} -import org.neo4j.cypher.internal.compiler.v3_2.{CompilationPhaseTracer, CypherCompilerConfiguration} -import org.neo4j.cypher.internal.frontend.v3_0.{InputPosition => InputPosition3_0} -import org.neo4j.cypher.internal.frontend.v3_2.InputPosition - -/** - * Contains necessary wrappers for supporting 3_0 in 3.1 - */ -object wrappersFor3_0 { - - def as3_0(config: CypherCompilerConfiguration) = - CypherCompilerConfiguration3_0(config.queryCacheSize, - config.statsDivergenceThreshold, - config.queryPlanTTL, - config.useErrorsOverWarnings, - config.idpMaxTableSize, - config.idpIterationDuration, - config.errorIfShortestPathFallbackUsedAtRuntime, - config.nonIndexedLabelWarningThreshold) - - /** This is awful but needed until 3_0 is updated no to send in the tracer here */ - def as3_0(tracer: CompilationPhaseTracer): v3_0.CompilationPhaseTracer = { - new v3_0.CompilationPhaseTracer { - override def beginPhase(phase: v3_0.CompilationPhaseTracer.CompilationPhase) = { - val wrappedPhase = - if (phase == v3_0.CompilationPhaseTracer.CompilationPhase.AST_REWRITE) - org.neo4j.cypher.internal.compiler.v3_2.CompilationPhaseTracer.CompilationPhase.AST_REWRITE - else if (phase == v3_0.CompilationPhaseTracer.CompilationPhase - .CODE_GENERATION) - org.neo4j.cypher.internal.compiler.v3_2.CompilationPhaseTracer.CompilationPhase.CODE_GENERATION - else if (phase == v3_0.CompilationPhaseTracer.CompilationPhase - .LOGICAL_PLANNING) - org.neo4j.cypher.internal.compiler.v3_2.CompilationPhaseTracer.CompilationPhase.LOGICAL_PLANNING - else if (phase == v3_0.CompilationPhaseTracer.CompilationPhase.PARSING) - org.neo4j.cypher.internal.compiler.v3_2.CompilationPhaseTracer.CompilationPhase.PARSING - else if (phase == v3_0.CompilationPhaseTracer.CompilationPhase - .PIPE_BUILDING) - org.neo4j.cypher.internal.compiler.v3_2.CompilationPhaseTracer.CompilationPhase.PIPE_BUILDING - else if (phase == v3_0.CompilationPhaseTracer.CompilationPhase - .SEMANTIC_CHECK) - org.neo4j.cypher.internal.compiler.v3_2.CompilationPhaseTracer.CompilationPhase.SEMANTIC_CHECK - else throw new InternalException(s"Cannot handle $phase in 2.3") - - val wrappedEvent = tracer.beginPhase(wrappedPhase) - - new CompilationPhaseEvent { - override def close(): Unit = wrappedEvent.close() - } - } - } - } - - def as3_0(pos: InputPosition): InputPosition3_0 = InputPosition3_0(pos.offset, pos.line, pos.column) -} diff --git a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/helpers/wrappersFor3_1.scala b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/helpers/wrappersFor3_1.scala new file mode 100644 index 0000000000000..a5caeec1ca54c --- /dev/null +++ b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/helpers/wrappersFor3_1.scala @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2002-2016 "Neo Technology," + * Network Engine for Objects in Lund AB [http://neotechnology.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.cypher.internal.helpers + +import org.neo4j.cypher.InternalException +import org.neo4j.cypher.internal.compiler.v3_1 +import org.neo4j.cypher.internal.compiler.v3_1.CompilationPhaseTracer.{CompilationPhaseEvent, CompilationPhase => v3_1Phase} +import org.neo4j.cypher.internal.compiler.v3_1.{CypherCompilerConfiguration => CypherCompilerConfiguration3_1} +import org.neo4j.cypher.internal.compiler.v3_2.CompilationPhaseTracer.{CompilationPhase => v3_2Phase} +import org.neo4j.cypher.internal.compiler.v3_2.{CompilationPhaseTracer, CypherCompilerConfiguration} +import org.neo4j.cypher.internal.frontend.v3_1.{InputPosition => InputPosition3_1} +import org.neo4j.cypher.internal.frontend.v3_2.InputPosition + +/** + * Contains necessary wrappers for supporting 3_0 in 3.1 + */ +object wrappersFor3_1 { + + def as3_1(config: CypherCompilerConfiguration) = + CypherCompilerConfiguration3_1(config.queryCacheSize, + config.statsDivergenceThreshold, + config.queryPlanTTL, + config.useErrorsOverWarnings, + config.idpMaxTableSize, + config.idpIterationDuration, + config.errorIfShortestPathFallbackUsedAtRuntime, + config.nonIndexedLabelWarningThreshold) + + /** This is awful but needed until 3_0 is updated no to send in the tracer here */ + def as3_1(tracer: CompilationPhaseTracer): v3_1.CompilationPhaseTracer = { + new v3_1.CompilationPhaseTracer { + override def beginPhase(phase: v3_1.CompilationPhaseTracer.CompilationPhase) = { + val wrappedPhase = phase match { + case v3_1Phase.AST_REWRITE => v3_2Phase.AST_REWRITE + case v3_1Phase.CODE_GENERATION => v3_2Phase.CODE_GENERATION + case v3_1Phase.LOGICAL_PLANNING => v3_2Phase.LOGICAL_PLANNING + case v3_1Phase.PARSING => v3_2Phase.PARSING + case v3_1Phase.PIPE_BUILDING => v3_2Phase.PIPE_BUILDING + case v3_1Phase.SEMANTIC_CHECK => v3_2Phase.SEMANTIC_CHECK + case _ => throw new InternalException(s"Cannot handle $phase in 3.2") + } + + val wrappedEvent = tracer.beginPhase(wrappedPhase) + + new CompilationPhaseEvent { + override def close(): Unit = wrappedEvent.close() + } + } + } + } + + def as3_1(pos: InputPosition): InputPosition3_1 = InputPosition3_1(pos.offset, pos.line, pos.column) +} diff --git a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/TransactionalContextWrapperv3_1.scala b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/TransactionalContextWrapperv3_1.scala index 245c7da2c34c1..a22f99baf632a 100644 --- a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/TransactionalContextWrapperv3_1.scala +++ b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/TransactionalContextWrapperv3_1.scala @@ -24,7 +24,7 @@ import org.neo4j.graphdb.{Lock, PropertyContainer} import org.neo4j.kernel.GraphDatabaseQueryService import org.neo4j.kernel.api.KernelTransaction.Revertable import org.neo4j.kernel.api.dbms.DbmsOperations -import org.neo4j.kernel.api.security.{AccessMode, SecurityContext} +import org.neo4j.kernel.api.security.SecurityContext import org.neo4j.kernel.api.txstate.TxStateHolder import org.neo4j.kernel.api.{ReadOperations, Statement} import org.neo4j.kernel.impl.query.TransactionalContext diff --git a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/TransactionalContextWrapperv3_0.scala b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/TransactionalContextWrapperv3_2.scala similarity index 87% rename from community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/TransactionalContextWrapperv3_0.scala rename to community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/TransactionalContextWrapperv3_2.scala index 6da041744a3d4..a615eb1ab992c 100644 --- a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/TransactionalContextWrapperv3_0.scala +++ b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/TransactionalContextWrapperv3_2.scala @@ -19,23 +19,23 @@ */ package org.neo4j.cypher.internal.spi -import org.neo4j.cypher.internal.compiler.v3_0.spi.QueryTransactionalContext +import org.neo4j.cypher.internal.compiler.v3_2.spi.QueryTransactionalContext import org.neo4j.graphdb.{Lock, PropertyContainer} import org.neo4j.kernel.GraphDatabaseQueryService import org.neo4j.kernel.api.KernelTransaction.Revertable import org.neo4j.kernel.api.dbms.DbmsOperations -import org.neo4j.kernel.api.security.{AccessMode, SecurityContext} +import org.neo4j.kernel.api.security.SecurityContext import org.neo4j.kernel.api.txstate.TxStateHolder import org.neo4j.kernel.api.{ReadOperations, Statement} import org.neo4j.kernel.impl.query.TransactionalContext -case class TransactionalContextWrapperv3_0(tc: TransactionalContext) extends QueryTransactionalContext { +case class TransactionalContextWrapperv3_2(tc: TransactionalContext) extends QueryTransactionalContext { override type ReadOps = ReadOperations override type DbmsOps = DbmsOperations - def getOrBeginNewIfClosed(): TransactionalContextWrapperv3_0 = TransactionalContextWrapperv3_0(tc.getOrBeginNewIfClosed()) + def getOrBeginNewIfClosed(): TransactionalContextWrapperv3_2 = TransactionalContextWrapperv3_2(tc.getOrBeginNewIfClosed()) def isOpen: Boolean = tc.isOpen diff --git a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v2_3/TransactionBoundPlanContext.scala b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v2_3/TransactionBoundPlanContext.scala index 78000d50df180..07e1ef8512c85 100644 --- a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v2_3/TransactionBoundPlanContext.scala +++ b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v2_3/TransactionBoundPlanContext.scala @@ -23,7 +23,7 @@ import org.neo4j.cypher.MissingIndexException import org.neo4j.cypher.internal.compiler.v2_3.pipes.EntityProducer import org.neo4j.cypher.internal.compiler.v2_3.pipes.matching.ExpanderStep import org.neo4j.cypher.internal.compiler.v2_3.spi._ -import org.neo4j.cypher.internal.spi.TransactionalContextWrapperv3_1 +import org.neo4j.cypher.internal.spi.TransactionalContextWrapperv3_2 import org.neo4j.graphdb.Node import org.neo4j.kernel.api.constraints.UniquenessConstraint import org.neo4j.kernel.api.exceptions.KernelException @@ -33,7 +33,7 @@ import org.neo4j.kernel.impl.transaction.log.TransactionIdStore import scala.collection.JavaConverters._ -class TransactionBoundPlanContext(tc: TransactionalContextWrapperv3_1) +class TransactionBoundPlanContext(tc: TransactionalContextWrapperv3_2) extends TransactionBoundTokenContext(tc.statement) with PlanContext { @Deprecated diff --git a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v2_3/TransactionBoundQueryContext.scala b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v2_3/TransactionBoundQueryContext.scala index e90e138800906..68de739a5f0bd 100644 --- a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v2_3/TransactionBoundQueryContext.scala +++ b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v2_3/TransactionBoundQueryContext.scala @@ -35,7 +35,7 @@ import org.neo4j.cypher.internal.compiler.v2_3.helpers.JavaConversionSupport._ import org.neo4j.cypher.internal.compiler.v2_3.pipes.matching.PatternNode import org.neo4j.cypher.internal.compiler.v2_3.spi._ import org.neo4j.cypher.internal.frontend.v2_3.{Bound, EntityNotFoundException, FailedIndexException, SemanticDirection} -import org.neo4j.cypher.internal.spi.{BeansAPIRelationshipIterator, TransactionalContextWrapperv3_1} +import org.neo4j.cypher.internal.spi.{BeansAPIRelationshipIterator, TransactionalContextWrapperv3_2} import org.neo4j.cypher.javacompat.internal.GraphDatabaseCypherService import org.neo4j.graphalgo.impl.path.ShortestPath import org.neo4j.graphalgo.impl.path.ShortestPath.ShortestPathPredicate @@ -53,7 +53,7 @@ import org.neo4j.kernel.impl.core.NodeManager import scala.collection.JavaConverters._ import scala.collection.{Iterator, mutable} -final class TransactionBoundQueryContext(tc: TransactionalContextWrapperv3_1) +final class TransactionBoundQueryContext(tc: TransactionalContextWrapperv3_2) extends TransactionBoundTokenContext(tc.statement) with QueryContext { override val nodeOps = new NodeOperations diff --git a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_1/BidirectionalTraversalMatcher.scala b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_1/BidirectionalTraversalMatcher.scala index 3c90a8af57e43..f1f8b744e18e1 100644 --- a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_1/BidirectionalTraversalMatcher.scala +++ b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_1/BidirectionalTraversalMatcher.scala @@ -21,10 +21,10 @@ package org.neo4j.cypher.internal.spi.v3_1 import java.util.function.Predicate -import org.neo4j.cypher.internal.compiler.v3_2._ -import org.neo4j.cypher.internal.compiler.v3_2.pipes.matching.{ExpanderStep, TraversalMatcher, TraversalPathExpander} -import org.neo4j.cypher.internal.compiler.v3_2.pipes.{EntityProducer, QueryState} -import org.neo4j.cypher.internal.compiler.v3_2.planDescription.Argument +import org.neo4j.cypher.internal.compiler.v3_1._ +import org.neo4j.cypher.internal.compiler.v3_1.pipes.matching.{ExpanderStep, TraversalMatcher, TraversalPathExpander} +import org.neo4j.cypher.internal.compiler.v3_1.pipes.{EntityProducer, QueryState} +import org.neo4j.cypher.internal.compiler.v3_1.planDescription.Argument import org.neo4j.graphdb.impl.traversal.StandardBranchCollisionDetector import org.neo4j.graphdb.traversal.{BranchCollisionPolicy, _} import org.neo4j.graphdb.{Node, Path} diff --git a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_1/ExceptionTranslatingPlanContext.scala b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_1/ExceptionTranslatingPlanContext.scala index 732a69a32c364..395b2e9167550 100644 --- a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_1/ExceptionTranslatingPlanContext.scala +++ b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_1/ExceptionTranslatingPlanContext.scala @@ -19,10 +19,10 @@ */ package org.neo4j.cypher.internal.spi.v3_1 -import org.neo4j.cypher.internal.compiler.v3_2.InternalNotificationLogger -import org.neo4j.cypher.internal.compiler.v3_2.pipes.EntityProducer -import org.neo4j.cypher.internal.compiler.v3_2.pipes.matching.{ExpanderStep, TraversalMatcher} -import org.neo4j.cypher.internal.compiler.v3_2.spi._ +import org.neo4j.cypher.internal.compiler.v3_1.InternalNotificationLogger +import org.neo4j.cypher.internal.compiler.v3_1.pipes.EntityProducer +import org.neo4j.cypher.internal.compiler.v3_1.pipes.matching.{ExpanderStep, TraversalMatcher} +import org.neo4j.cypher.internal.compiler.v3_1.spi._ import org.neo4j.graphdb.Node import org.neo4j.kernel.api.constraints.UniquenessConstraint import org.neo4j.kernel.api.index.IndexDescriptor diff --git a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_1/ExceptionTranslationSupport.scala b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_1/ExceptionTranslationSupport.scala index f186eb4965db4..07ff7bafffe94 100644 --- a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_1/ExceptionTranslationSupport.scala +++ b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_1/ExceptionTranslationSupport.scala @@ -19,7 +19,7 @@ */ package org.neo4j.cypher.internal.spi.v3_1 -import org.neo4j.cypher.internal.compiler.v3_2.spi.TokenContext +import org.neo4j.cypher.internal.compiler.v3_1.spi.TokenContext import org.neo4j.cypher.{ConstraintValidationException, CypherExecutionException} import org.neo4j.graphdb.{ConstraintViolationException => KernelConstraintViolationException} import org.neo4j.kernel.api.TokenNameLookup diff --git a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_1/HardcodedGraphStatistics.scala b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_1/HardcodedGraphStatistics.scala index ca96eceaf6da7..88c0fc1121ad4 100644 --- a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_1/HardcodedGraphStatistics.scala +++ b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_1/HardcodedGraphStatistics.scala @@ -22,4 +22,4 @@ package org.neo4j.cypher.internal.spi.v3_1 //This class should live here, but until we have to touch //disk, let's have it in the compiler. Convenient. case object HardcodedGraphStatistics - extends org.neo4j.cypher.internal.compiler.v3_2.HardcodedGraphStatisticsValues + extends org.neo4j.cypher.internal.compiler.v3_1.HardcodedGraphStatisticsValues diff --git a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_1/MonodirectionalTraversalMatcher.scala b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_1/MonodirectionalTraversalMatcher.scala index 6951947130977..ee1adaa175fc5 100644 --- a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_1/MonodirectionalTraversalMatcher.scala +++ b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_1/MonodirectionalTraversalMatcher.scala @@ -19,10 +19,10 @@ */ package org.neo4j.cypher.internal.spi.v3_1 -import org.neo4j.cypher.internal.compiler.v3_2._ -import org.neo4j.cypher.internal.compiler.v3_2.pipes.matching.{ExpanderStep, TraversalMatcher, TraversalPathExpander} -import org.neo4j.cypher.internal.compiler.v3_2.pipes.{EntityProducer, QueryState} -import org.neo4j.cypher.internal.compiler.v3_2.planDescription.Argument +import org.neo4j.cypher.internal.compiler.v3_1._ +import org.neo4j.cypher.internal.compiler.v3_1.pipes.matching.{ExpanderStep, TraversalMatcher, TraversalPathExpander} +import org.neo4j.cypher.internal.compiler.v3_1.pipes.{EntityProducer, QueryState} +import org.neo4j.cypher.internal.compiler.v3_1.planDescription.Argument import org.neo4j.graphdb.traversal._ import org.neo4j.graphdb.{Node, Path} import org.neo4j.graphdb.traversal.Uniqueness diff --git a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_1/TransactionBoundGraphStatistics.scala b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_1/TransactionBoundGraphStatistics.scala index 0dda83ea93e75..2ebb9c19eaee3 100644 --- a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_1/TransactionBoundGraphStatistics.scala +++ b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_1/TransactionBoundGraphStatistics.scala @@ -19,12 +19,12 @@ */ package org.neo4j.cypher.internal.spi.v3_1 -import org.neo4j.cypher.internal.compiler.v3_2.planner.logical.{Cardinality, Selectivity} -import org.neo4j.cypher.internal.compiler.v3_2.spi.{GraphStatistics, StatisticsCompletingGraphStatistics} -import org.neo4j.cypher.internal.frontend.v3_2.{LabelId, NameId, PropertyKeyId, RelTypeId} +import org.neo4j.cypher.internal.compiler.v3_1.planner.logical.{Cardinality, Selectivity} +import org.neo4j.cypher.internal.compiler.v3_1.spi.{GraphStatistics, StatisticsCompletingGraphStatistics} +import org.neo4j.cypher.internal.frontend.v3_1.{LabelId, NameId, PropertyKeyId, RelTypeId} +import org.neo4j.kernel.api.ReadOperations import org.neo4j.kernel.api.exceptions.index.IndexNotFoundKernelException import org.neo4j.kernel.api.index.IndexDescriptor -import org.neo4j.kernel.api.{ReadOperations, Statement => KernelStatement} object TransactionBoundGraphStatistics { def apply(ops: ReadOperations) = new StatisticsCompletingGraphStatistics(new BaseTransactionBoundGraphStatistics(ops)) diff --git a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_1/TransactionBoundPlanContext.scala b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_1/TransactionBoundPlanContext.scala index bbfbe4d55d737..70c3ebcd01963 100644 --- a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_1/TransactionBoundPlanContext.scala +++ b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_1/TransactionBoundPlanContext.scala @@ -23,12 +23,12 @@ import java.util.Optional import org.neo4j.cypher.MissingIndexException import org.neo4j.cypher.internal.LastCommittedTxIdProvider -import org.neo4j.cypher.internal.compiler.v3_2.InternalNotificationLogger -import org.neo4j.cypher.internal.compiler.v3_2.pipes.EntityProducer -import org.neo4j.cypher.internal.compiler.v3_2.pipes.matching.ExpanderStep -import org.neo4j.cypher.internal.compiler.v3_2.spi._ -import org.neo4j.cypher.internal.frontend.v3_2.symbols.CypherType -import org.neo4j.cypher.internal.frontend.v3_2.{CypherExecutionException, symbols} +import org.neo4j.cypher.internal.compiler.v3_1.InternalNotificationLogger +import org.neo4j.cypher.internal.compiler.v3_1.pipes.EntityProducer +import org.neo4j.cypher.internal.compiler.v3_1.pipes.matching.ExpanderStep +import org.neo4j.cypher.internal.compiler.v3_1.spi._ +import org.neo4j.cypher.internal.frontend.v3_1.symbols.CypherType +import org.neo4j.cypher.internal.frontend.v3_1.{CypherExecutionException, symbols} import org.neo4j.cypher.internal.spi.TransactionalContextWrapperv3_1 import org.neo4j.graphdb.Node import org.neo4j.kernel.api.constraints.UniquenessConstraint diff --git a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_1/TransactionBoundQueryContext.scala b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_1/TransactionBoundQueryContext.scala index db25383cfb2f6..9c4864f757442 100644 --- a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_1/TransactionBoundQueryContext.scala +++ b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_1/TransactionBoundQueryContext.scala @@ -25,16 +25,16 @@ import java.util.function.Predicate import org.neo4j.collection.RawIterator import org.neo4j.collection.primitive.PrimitiveLongIterator import org.neo4j.collection.primitive.base.Empty.EMPTY_PRIMITIVE_LONG_COLLECTION -import org.neo4j.cypher.internal.compiler.v3_2.MinMaxOrdering.{BY_NUMBER, BY_STRING, BY_VALUE} -import org.neo4j.cypher.internal.compiler.v3_2._ -import org.neo4j.cypher.internal.compiler.v3_2.ast.convert.commands.DirectionConverter.toGraphDb -import org.neo4j.cypher.internal.compiler.v3_2.commands.expressions -import org.neo4j.cypher.internal.compiler.v3_2.commands.expressions.{KernelPredicate, OnlyDirectionExpander, TypeAndDirectionExpander} -import org.neo4j.cypher.internal.compiler.v3_2.helpers.JavaConversionSupport -import org.neo4j.cypher.internal.compiler.v3_2.helpers.JavaConversionSupport._ -import org.neo4j.cypher.internal.compiler.v3_2.pipes.matching.PatternNode -import org.neo4j.cypher.internal.compiler.v3_2.spi._ -import org.neo4j.cypher.internal.frontend.v3_2.{Bound, EntityNotFoundException, FailedIndexException, SemanticDirection} +import org.neo4j.cypher.internal.compiler.v3_1.MinMaxOrdering.{BY_NUMBER, BY_STRING, BY_VALUE} +import org.neo4j.cypher.internal.compiler.v3_1._ +import org.neo4j.cypher.internal.compiler.v3_1.ast.convert.commands.DirectionConverter.toGraphDb +import org.neo4j.cypher.internal.compiler.v3_1.commands.expressions +import org.neo4j.cypher.internal.compiler.v3_1.commands.expressions.{KernelPredicate, OnlyDirectionExpander, TypeAndDirectionExpander} +import org.neo4j.cypher.internal.compiler.v3_1.helpers.JavaConversionSupport +import org.neo4j.cypher.internal.compiler.v3_1.helpers.JavaConversionSupport._ +import org.neo4j.cypher.internal.compiler.v3_1.pipes.matching.PatternNode +import org.neo4j.cypher.internal.compiler.v3_1.spi._ +import org.neo4j.cypher.internal.frontend.v3_1.{Bound, EntityNotFoundException, FailedIndexException, SemanticDirection} import org.neo4j.cypher.internal.spi.v3_1.TransactionBoundQueryContext.IndexSearchMonitor import org.neo4j.cypher.internal.spi.{BeansAPIRelationshipIterator, TransactionalContextWrapperv3_1} import org.neo4j.cypher.javacompat.internal.GraphDatabaseCypherService @@ -48,6 +48,7 @@ import org.neo4j.graphdb.traversal.{Evaluators, TraversalDescription, Uniqueness import org.neo4j.kernel.GraphDatabaseQueryService import org.neo4j.kernel.api._ import org.neo4j.kernel.api.constraints.{NodePropertyExistenceConstraint, RelationshipPropertyExistenceConstraint, UniquenessConstraint} +import org.neo4j.kernel.api.dbms.DbmsOperations import org.neo4j.kernel.api.exceptions.ProcedureException import org.neo4j.kernel.api.exceptions.schema.{AlreadyConstrainedException, AlreadyIndexedException} import org.neo4j.kernel.api.index.{IndexDescriptor, InternalIndexState} @@ -58,25 +59,25 @@ import org.neo4j.kernel.impl.locking.ResourceTypes import scala.collection.Iterator import scala.collection.JavaConverters._ -final class TransactionBoundQueryContext(val transactionalContext: TransactionalContextWrapperv3_1)(implicit indexSearchMonitor: IndexSearchMonitor) - extends TransactionBoundTokenContext(transactionalContext.statement) with QueryContext { +final class TransactionBoundQueryContext(txContext: TransactionalContextWrapperv3_1)(implicit indexSearchMonitor: IndexSearchMonitor) + extends TransactionBoundTokenContext(txContext.statement) with QueryContext { type EntityAccessor = NodeManager val nodeOps = new NodeOperations val relationshipOps = new RelationshipOperations - override lazy val entityAccessor = transactionalContext.graph.getDependencyResolver.resolveDependency(classOf[NodeManager]) + override lazy val entityAccessor = txContext.graph.getDependencyResolver.resolveDependency(classOf[NodeManager]) override def setLabelsOnNode(node: Long, labelIds: Iterator[Int]): Int = labelIds.foldLeft(0) { - case (count, labelId) => if (transactionalContext.statement.dataWriteOperations().nodeAddLabel(node, labelId)) count + 1 else count + case (count, labelId) => if (txContext.statement.dataWriteOperations().nodeAddLabel(node, labelId)) count + 1 else count } override def withAnyOpenQueryContext[T](work: (QueryContext) => T): T = { - if (transactionalContext.isOpen) { + if (txContext.isOpen) { work(this) } else { - val context = transactionalContext.getOrBeginNewIfClosed() + val context = txContext.getOrBeginNewIfClosed() var success = false try { val result = work(new TransactionBoundQueryContext(context)) @@ -89,21 +90,21 @@ final class TransactionBoundQueryContext(val transactionalContext: Transactional } override def createNode(): Node = - transactionalContext.graph.createNode() + txContext.graph.createNode() override def createRelationship(start: Node, end: Node, relType: String) = start.createRelationshipTo(end, withName(relType)) override def createRelationship(start: Long, end: Long, relType: Int) = { - val relId = transactionalContext.statement.dataWriteOperations().relationshipCreate(relType, start, end) + val relId = txContext.statement.dataWriteOperations().relationshipCreate(relType, start, end) relationshipOps.getById(relId) } override def getOrCreateRelTypeId(relTypeName: String): Int = - transactionalContext.statement.tokenWriteOperations().relationshipTypeGetOrCreateForName(relTypeName) + txContext.statement.tokenWriteOperations().relationshipTypeGetOrCreateForName(relTypeName) override def getLabelsForNode(node: Long) = try { - JavaConversionSupport.asScala(transactionalContext.statement.readOperations().nodeGetLabels(node)) + JavaConversionSupport.asScala(txContext.statement.readOperations().nodeGetLabels(node)) } catch { case e: org.neo4j.kernel.api.exceptions.EntityNotFoundException => if (nodeOps.isDeletedInThisTx(node)) @@ -113,30 +114,30 @@ final class TransactionBoundQueryContext(val transactionalContext: Transactional } override def getPropertiesForNode(node: Long) = - JavaConversionSupport.asScala(transactionalContext.statement.readOperations().nodeGetPropertyKeys(node)) + JavaConversionSupport.asScala(txContext.statement.readOperations().nodeGetPropertyKeys(node)) override def getPropertiesForRelationship(relId: Long) = - JavaConversionSupport.asScala(transactionalContext.statement.readOperations().relationshipGetPropertyKeys(relId)) + JavaConversionSupport.asScala(txContext.statement.readOperations().relationshipGetPropertyKeys(relId)) override def isLabelSetOnNode(label: Int, node: Long) = - transactionalContext.statement.readOperations().nodeHasLabel(node, label) + txContext.statement.readOperations().nodeHasLabel(node, label) override def getOrCreateLabelId(labelName: String) = - transactionalContext.statement.tokenWriteOperations().labelGetOrCreateForName(labelName) + txContext.statement.tokenWriteOperations().labelGetOrCreateForName(labelName) def getRelationshipsForIds(node: Node, dir: SemanticDirection, types: Option[Seq[Int]]): Iterator[Relationship] = { val relationships = types match { case None => - transactionalContext.statement.readOperations().nodeGetRelationships(node.getId, toGraphDb(dir)) + txContext.statement.readOperations().nodeGetRelationships(node.getId, toGraphDb(dir)) case Some(typeIds) => - transactionalContext.statement.readOperations().nodeGetRelationships(node.getId, toGraphDb(dir), typeIds: _*) + txContext.statement.readOperations().nodeGetRelationships(node.getId, toGraphDb(dir), typeIds: _*) } new BeansAPIRelationshipIterator(relationships, entityAccessor) } override def indexSeek(index: IndexDescriptor, value: Any) = { indexSearchMonitor.indexSeek(index, value) - JavaConversionSupport.mapToScalaENFXSafe(transactionalContext.statement.readOperations().nodesGetFromIndexSeek(index, value))(nodeOps.getById) + JavaConversionSupport.mapToScalaENFXSafe(txContext.statement.readOperations().nodesGetFromIndexSeek(index, value))(nodeOps.getById) } override def indexSeekByRange(index: IndexDescriptor, value: Any) = value match { @@ -199,12 +200,12 @@ final class TransactionBoundQueryContext(val transactionalContext: Transactional } private def indexSeekByPrefixRange(index: IndexDescriptor, prefix: String): scala.Iterator[Node] = { - val indexedNodes = transactionalContext.statement.readOperations().nodesGetFromIndexRangeSeekByPrefix(index, prefix) + val indexedNodes = txContext.statement.readOperations().nodesGetFromIndexRangeSeekByPrefix(index, prefix) JavaConversionSupport.mapToScalaENFXSafe(indexedNodes)(nodeOps.getById) } private def indexSeekByNumericalRange(index: IndexDescriptor, range: InequalitySeekRange[Number]): scala.Iterator[Node] = { - val readOps = transactionalContext.statement.readOperations() + val readOps = txContext.statement.readOperations() val matchingNodes: PrimitiveLongIterator = (range match { case rangeLessThan: RangeLessThan[Number] => @@ -231,8 +232,7 @@ final class TransactionBoundQueryContext(val transactionalContext: Transactional } private def indexSeekByStringRange(index: IndexDescriptor, range: InequalitySeekRange[String]): scala.Iterator[Node] = { - val readOps = transactionalContext.statement.readOperations() - val propertyKeyId = index.getPropertyKeyId + val readOps = txContext.statement.readOperations() val matchingNodes: PrimitiveLongIterator = range match { case rangeLessThan: RangeLessThan[String] => @@ -260,53 +260,53 @@ final class TransactionBoundQueryContext(val transactionalContext: Transactional } override def indexScan(index: IndexDescriptor) = - mapToScalaENFXSafe(transactionalContext.statement.readOperations().nodesGetFromIndexScan(index))(nodeOps.getById) + mapToScalaENFXSafe(txContext.statement.readOperations().nodesGetFromIndexScan(index))(nodeOps.getById) override def indexScanByContains(index: IndexDescriptor, value: String) = - mapToScalaENFXSafe(transactionalContext.statement.readOperations().nodesGetFromIndexContainsScan(index, value))(nodeOps.getById) + mapToScalaENFXSafe(txContext.statement.readOperations().nodesGetFromIndexContainsScan(index, value))(nodeOps.getById) override def indexScanByEndsWith(index: IndexDescriptor, value: String) = - mapToScalaENFXSafe(transactionalContext.statement.readOperations().nodesGetFromIndexEndsWithScan(index, value))(nodeOps.getById) + mapToScalaENFXSafe(txContext.statement.readOperations().nodesGetFromIndexEndsWithScan(index, value))(nodeOps.getById) override def lockingUniqueIndexSeek(index: IndexDescriptor, value: Any): Option[Node] = { indexSearchMonitor.lockingUniqueIndexSeek(index, value) - val nodeId = transactionalContext.statement.readOperations().nodeGetFromUniqueIndexSeek(index, value) + val nodeId = txContext.statement.readOperations().nodeGetFromUniqueIndexSeek(index, value) if (StatementConstants.NO_SUCH_NODE == nodeId) None else Some(nodeOps.getById(nodeId)) } override def removeLabelsFromNode(node: Long, labelIds: Iterator[Int]): Int = labelIds.foldLeft(0) { case (count, labelId) => - if (transactionalContext.statement.dataWriteOperations().nodeRemoveLabel(node, labelId)) count + 1 else count + if (txContext.statement.dataWriteOperations().nodeRemoveLabel(node, labelId)) count + 1 else count } override def getNodesByLabel(id: Int): Iterator[Node] = - JavaConversionSupport.mapToScalaENFXSafe(transactionalContext.statement.readOperations().nodesGetForLabel(id))(nodeOps.getById) + JavaConversionSupport.mapToScalaENFXSafe(txContext.statement.readOperations().nodesGetForLabel(id))(nodeOps.getById) override def nodeGetDegree(node: Long, dir: SemanticDirection): Int = - transactionalContext.statement.readOperations().nodeGetDegree(node, toGraphDb(dir)) + txContext.statement.readOperations().nodeGetDegree(node, toGraphDb(dir)) override def nodeGetDegree(node: Long, dir: SemanticDirection, relTypeId: Int): Int = - transactionalContext.statement.readOperations().nodeGetDegree(node, toGraphDb(dir), relTypeId) + txContext.statement.readOperations().nodeGetDegree(node, toGraphDb(dir), relTypeId) - override def nodeIsDense(node: Long): Boolean = transactionalContext.statement.readOperations().nodeIsDense(node) + override def nodeIsDense(node: Long): Boolean = txContext.statement.readOperations().nodeIsDense(node) class NodeOperations extends BaseOperations[Node] { override def delete(obj: Node) { try { - transactionalContext.statement.dataWriteOperations().nodeDelete(obj.getId) + txContext.statement.dataWriteOperations().nodeDelete(obj.getId) } catch { case _: exceptions.EntityNotFoundException => // node has been deleted by another transaction, oh well... } } override def propertyKeyIds(id: Long): Iterator[Int] = try { - JavaConversionSupport.asScalaENFXSafe(transactionalContext.statement.readOperations().nodeGetPropertyKeys(id)) + JavaConversionSupport.asScalaENFXSafe(txContext.statement.readOperations().nodeGetPropertyKeys(id)) } catch { case _: exceptions.EntityNotFoundException => Iterator.empty } override def getProperty(id: Long, propertyKeyId: Int): Any = try { - transactionalContext.statement.readOperations().nodeGetProperty(id, propertyKeyId) + txContext.statement.readOperations().nodeGetProperty(id, propertyKeyId) } catch { case e: org.neo4j.kernel.api.exceptions.EntityNotFoundException => if (isDeletedInThisTx(id)) @@ -316,14 +316,14 @@ final class TransactionBoundQueryContext(val transactionalContext: Transactional } override def hasProperty(id: Long, propertyKey: Int) = try { - transactionalContext.statement.readOperations().nodeHasProperty(id, propertyKey) + txContext.statement.readOperations().nodeHasProperty(id, propertyKey) } catch { case _: exceptions.EntityNotFoundException => false } override def removeProperty(id: Long, propertyKeyId: Int) { try { - transactionalContext.statement.dataWriteOperations().nodeRemoveProperty(id, propertyKeyId) + txContext.statement.dataWriteOperations().nodeRemoveProperty(id, propertyKeyId) } catch { case _: exceptions.EntityNotFoundException => //ignore } @@ -331,57 +331,57 @@ final class TransactionBoundQueryContext(val transactionalContext: Transactional override def setProperty(id: Long, propertyKeyId: Int, value: Any) { try { - transactionalContext.statement.dataWriteOperations().nodeSetProperty(id, properties.Property.property(propertyKeyId, value) ) + txContext.statement.dataWriteOperations().nodeSetProperty(id, properties.Property.property(propertyKeyId, value) ) } catch { case _: exceptions.EntityNotFoundException => //ignore } } override def getById(id: Long) = try { - transactionalContext.graph.getNodeById(id) + txContext.graph.getNodeById(id) } catch { case e: NotFoundException => throw new EntityNotFoundException(s"Node with id $id", e) } override def all: Iterator[Node] = - JavaConversionSupport.mapToScalaENFXSafe(transactionalContext.statement.readOperations().nodesGetAll())(getById) + JavaConversionSupport.mapToScalaENFXSafe(txContext.statement.readOperations().nodesGetAll())(getById) override def indexGet(name: String, key: String, value: Any): Iterator[Node] = - JavaConversionSupport.mapToScalaENFXSafe(transactionalContext.statement.readOperations().nodeLegacyIndexGet(name, key, value))(getById) + JavaConversionSupport.mapToScalaENFXSafe(txContext.statement.readOperations().nodeLegacyIndexGet(name, key, value))(getById) override def indexQuery(name: String, query: Any): Iterator[Node] = - JavaConversionSupport.mapToScalaENFXSafe(transactionalContext.statement.readOperations().nodeLegacyIndexQuery(name, query))(getById) + JavaConversionSupport.mapToScalaENFXSafe(txContext.statement.readOperations().nodeLegacyIndexQuery(name, query))(getById) override def isDeletedInThisTx(n: Node): Boolean = isDeletedInThisTx(n.getId) def isDeletedInThisTx(id: Long): Boolean = - transactionalContext.stateView.hasTxStateWithChanges && transactionalContext.stateView.txState().nodeIsDeletedInThisTx(id) + txContext.stateView.hasTxStateWithChanges && txContext.stateView.txState().nodeIsDeletedInThisTx(id) override def acquireExclusiveLock(obj: Long) = - transactionalContext.statement.readOperations().acquireExclusive(ResourceTypes.NODE, obj) + txContext.statement.readOperations().acquireExclusive(ResourceTypes.NODE, obj) override def releaseExclusiveLock(obj: Long) = - transactionalContext.statement.readOperations().releaseExclusive(ResourceTypes.NODE, obj) + txContext.statement.readOperations().releaseExclusive(ResourceTypes.NODE, obj) } class RelationshipOperations extends BaseOperations[Relationship] { override def delete(obj: Relationship) { try { - transactionalContext.statement.dataWriteOperations().relationshipDelete(obj.getId) + txContext.statement.dataWriteOperations().relationshipDelete(obj.getId) } catch { case _: exceptions.EntityNotFoundException => // node has been deleted by another transaction, oh well... } } override def propertyKeyIds(id: Long): Iterator[Int] = try { - asScalaENFXSafe(transactionalContext.statement.readOperations().relationshipGetPropertyKeys(id)) + asScalaENFXSafe(txContext.statement.readOperations().relationshipGetPropertyKeys(id)) } catch { case _: exceptions.EntityNotFoundException => Iterator.empty } override def getProperty(id: Long, propertyKeyId: Int): Any = try { - transactionalContext.statement.readOperations().relationshipGetProperty(id, propertyKeyId) + txContext.statement.readOperations().relationshipGetProperty(id, propertyKeyId) } catch { case e: org.neo4j.kernel.api.exceptions.EntityNotFoundException => if (isDeletedInThisTx(id)) @@ -391,14 +391,14 @@ final class TransactionBoundQueryContext(val transactionalContext: Transactional } override def hasProperty(id: Long, propertyKey: Int) = try { - transactionalContext.statement.readOperations().relationshipHasProperty(id, propertyKey) + txContext.statement.readOperations().relationshipHasProperty(id, propertyKey) } catch { case _: exceptions.EntityNotFoundException => false } override def removeProperty(id: Long, propertyKeyId: Int) { try { - transactionalContext.statement.dataWriteOperations().relationshipRemoveProperty(id, propertyKeyId) + txContext.statement.dataWriteOperations().relationshipRemoveProperty(id, propertyKeyId) } catch { case _: exceptions.EntityNotFoundException => //ignore } @@ -406,43 +406,43 @@ final class TransactionBoundQueryContext(val transactionalContext: Transactional override def setProperty(id: Long, propertyKeyId: Int, value: Any) { try { - transactionalContext.statement.dataWriteOperations().relationshipSetProperty(id, properties.Property.property(propertyKeyId, value)) + txContext.statement.dataWriteOperations().relationshipSetProperty(id, properties.Property.property(propertyKeyId, value)) } catch { case _: exceptions.EntityNotFoundException => //ignore } } override def getById(id: Long) = try { - transactionalContext.graph.getRelationshipById(id) + txContext.graph.getRelationshipById(id) } catch { case e: NotFoundException => throw new EntityNotFoundException(s"Relationship with id $id", e) } override def all: Iterator[Relationship] = { - JavaConversionSupport.mapToScalaENFXSafe(transactionalContext.statement.readOperations().relationshipsGetAll())(getById) + JavaConversionSupport.mapToScalaENFXSafe(txContext.statement.readOperations().relationshipsGetAll())(getById) } override def indexGet(name: String, key: String, value: Any): Iterator[Relationship] = - JavaConversionSupport.mapToScalaENFXSafe(transactionalContext.statement.readOperations().relationshipLegacyIndexGet(name, key, value, -1, -1))(getById) + JavaConversionSupport.mapToScalaENFXSafe(txContext.statement.readOperations().relationshipLegacyIndexGet(name, key, value, -1, -1))(getById) override def indexQuery(name: String, query: Any): Iterator[Relationship] = - JavaConversionSupport.mapToScalaENFXSafe(transactionalContext.statement.readOperations().relationshipLegacyIndexQuery(name, query, -1, -1))(getById) + JavaConversionSupport.mapToScalaENFXSafe(txContext.statement.readOperations().relationshipLegacyIndexQuery(name, query, -1, -1))(getById) override def isDeletedInThisTx(r: Relationship): Boolean = isDeletedInThisTx(r.getId) def isDeletedInThisTx(id: Long): Boolean = - transactionalContext.stateView.hasTxStateWithChanges && transactionalContext.stateView.txState().relationshipIsDeletedInThisTx(id) + txContext.stateView.hasTxStateWithChanges && txContext.stateView.txState().relationshipIsDeletedInThisTx(id) override def acquireExclusiveLock(obj: Long) = - transactionalContext.statement.readOperations().acquireExclusive(ResourceTypes.RELATIONSHIP, obj) + txContext.statement.readOperations().acquireExclusive(ResourceTypes.RELATIONSHIP, obj) override def releaseExclusiveLock(obj: Long) = - transactionalContext.statement.readOperations().acquireExclusive(ResourceTypes.RELATIONSHIP, obj) + txContext.statement.readOperations().acquireExclusive(ResourceTypes.RELATIONSHIP, obj) } override def getOrCreatePropertyKeyId(propertyKey: String) = - transactionalContext.statement.tokenWriteOperations().propertyKeyGetOrCreateForName(propertyKey) + txContext.statement.tokenWriteOperations().propertyKeyGetOrCreateForName(propertyKey) abstract class BaseOperations[T <: PropertyContainer] extends Operations[T] { def primitiveLongIteratorToScalaIterator(primitiveIterator: PrimitiveLongIterator): Iterator[Long] = @@ -457,55 +457,55 @@ final class TransactionBoundQueryContext(val transactionalContext: Transactional val javaCreator = new java.util.function.Function[K, V]() { override def apply(key: K) = creator } - transactionalContext.statement.readOperations().schemaStateGetOrCreate(key, javaCreator) + txContext.statement.readOperations().schemaStateGetOrCreate(key, javaCreator) } override def addIndexRule(labelId: Int, propertyKeyId: Int): IdempotentResult[IndexDescriptor] = try { - IdempotentResult(transactionalContext.statement.schemaWriteOperations().indexCreate(labelId, propertyKeyId)) + IdempotentResult(txContext.statement.schemaWriteOperations().indexCreate(labelId, propertyKeyId)) } catch { case _: AlreadyIndexedException => - val indexDescriptor = transactionalContext.statement.readOperations().indexGetForLabelAndPropertyKey(labelId, propertyKeyId) - if(transactionalContext.statement.readOperations().indexGetState(indexDescriptor) == InternalIndexState.FAILED) + val indexDescriptor = txContext.statement.readOperations().indexGetForLabelAndPropertyKey(labelId, propertyKeyId) + if(txContext.statement.readOperations().indexGetState(indexDescriptor) == InternalIndexState.FAILED) throw new FailedIndexException(indexDescriptor.userDescription(tokenNameLookup)) IdempotentResult(indexDescriptor, wasCreated = false) } override def dropIndexRule(labelId: Int, propertyKeyId: Int) = - transactionalContext.statement.schemaWriteOperations().indexDrop(new IndexDescriptor(labelId, propertyKeyId)) + txContext.statement.schemaWriteOperations().indexDrop(new IndexDescriptor(labelId, propertyKeyId)) override def createUniqueConstraint(labelId: Int, propertyKeyId: Int): IdempotentResult[UniquenessConstraint] = try { - IdempotentResult(transactionalContext.statement.schemaWriteOperations().uniquePropertyConstraintCreate(labelId, propertyKeyId)) + IdempotentResult(txContext.statement.schemaWriteOperations().uniquePropertyConstraintCreate(labelId, propertyKeyId)) } catch { case existing: AlreadyConstrainedException => IdempotentResult(existing.constraint().asInstanceOf[UniquenessConstraint], wasCreated = false) } override def dropUniqueConstraint(labelId: Int, propertyKeyId: Int) = - transactionalContext.statement.schemaWriteOperations().constraintDrop(new UniquenessConstraint(labelId, propertyKeyId)) + txContext.statement.schemaWriteOperations().constraintDrop(new UniquenessConstraint(labelId, propertyKeyId)) override def createNodePropertyExistenceConstraint(labelId: Int, propertyKeyId: Int): IdempotentResult[NodePropertyExistenceConstraint] = try { - IdempotentResult(transactionalContext.statement.schemaWriteOperations().nodePropertyExistenceConstraintCreate(labelId, propertyKeyId)) + IdempotentResult(txContext.statement.schemaWriteOperations().nodePropertyExistenceConstraintCreate(labelId, propertyKeyId)) } catch { case existing: AlreadyConstrainedException => IdempotentResult(existing.constraint().asInstanceOf[NodePropertyExistenceConstraint], wasCreated = false) } override def dropNodePropertyExistenceConstraint(labelId: Int, propertyKeyId: Int) = - transactionalContext.statement.schemaWriteOperations().constraintDrop(new NodePropertyExistenceConstraint(labelId, propertyKeyId)) + txContext.statement.schemaWriteOperations().constraintDrop(new NodePropertyExistenceConstraint(labelId, propertyKeyId)) override def createRelationshipPropertyExistenceConstraint(relTypeId: Int, propertyKeyId: Int): IdempotentResult[RelationshipPropertyExistenceConstraint] = try { - IdempotentResult(transactionalContext.statement.schemaWriteOperations().relationshipPropertyExistenceConstraintCreate(relTypeId, propertyKeyId)) + IdempotentResult(txContext.statement.schemaWriteOperations().relationshipPropertyExistenceConstraintCreate(relTypeId, propertyKeyId)) } catch { case existing: AlreadyConstrainedException => IdempotentResult(existing.constraint().asInstanceOf[RelationshipPropertyExistenceConstraint], wasCreated = false) } override def dropRelationshipPropertyExistenceConstraint(relTypeId: Int, propertyKeyId: Int) = - transactionalContext.statement.schemaWriteOperations().constraintDrop(new RelationshipPropertyExistenceConstraint(relTypeId, propertyKeyId)) + txContext.statement.schemaWriteOperations().constraintDrop(new RelationshipPropertyExistenceConstraint(relTypeId, propertyKeyId)) - override def getImportURL(url: URL): Either[String,URL] = transactionalContext.graph match { + override def getImportURL(url: URL): Either[String,URL] = txContext.graph match { case db: GraphDatabaseQueryService => try { Right(db.validateURLAccess(url)) @@ -518,7 +518,7 @@ final class TransactionBoundQueryContext(val transactionalContext: Transactional override def relationshipEndNode(rel: Relationship) = rel.getEndNode - private lazy val tokenNameLookup = new StatementTokenNameLookup(transactionalContext.statement.readOperations()) + private lazy val tokenNameLookup = new StatementTokenNameLookup(txContext.statement.readOperations()) // Legacy dependency between kernel and compiler override def variableLengthPathExpand(node: PatternNode, @@ -536,7 +536,7 @@ final class TransactionBoundQueryContext(val transactionalContext: Transactional // The RULE compiler makes use of older kernel API capabilities for variable length expanding // TODO: Consider re-writing this using similar code to the COST var-length expand - val baseTraversalDescription: TraversalDescription = transactionalContext.graph.asInstanceOf[GraphDatabaseCypherService] + val baseTraversalDescription: TraversalDescription = txContext.graph.asInstanceOf[GraphDatabaseCypherService] .getGraphDatabaseService .traversalDescription() .evaluator(depthEval) @@ -555,18 +555,18 @@ final class TransactionBoundQueryContext(val transactionalContext: Transactional } override def nodeCountByCountStore(labelId: Int): Long = { - transactionalContext.statement.readOperations().countsForNode(labelId) + txContext.statement.readOperations().countsForNode(labelId) } override def relationshipCountByCountStore(startLabelId: Int, typeId: Int, endLabelId: Int): Long = { - transactionalContext.statement.readOperations().countsForRelationship(startLabelId, typeId, endLabelId) + txContext.statement.readOperations().countsForRelationship(startLabelId, typeId, endLabelId) } override def lockNodes(nodeIds: Long*) = - nodeIds.sorted.foreach(transactionalContext.statement.readOperations().acquireExclusive(ResourceTypes.NODE, _)) + nodeIds.sorted.foreach(txContext.statement.readOperations().acquireExclusive(ResourceTypes.NODE, _)) override def lockRelationships(relIds: Long*) = - relIds.sorted.foreach(transactionalContext.statement.readOperations().acquireExclusive(ResourceTypes.RELATIONSHIP, _)) + relIds.sorted.foreach(txContext.statement.readOperations().acquireExclusive(ResourceTypes.RELATIONSHIP, _)) override def singleShortestPath(left: Node, right: Node, depth: Int, expander: expressions.Expander, pathPredicate: KernelPredicate[Path], @@ -590,39 +590,39 @@ final class TransactionBoundQueryContext(val transactionalContext: Transactional private def shouldElevate(allowed: Array[String]): Boolean = { // We have to be careful with elevation, since we cannot elevate permissions in a nested procedure call // above the original allowed procedure mode. We enforce this by checking if mode is already an overridden mode. - val accessMode = transactionalContext.securityContext.mode() + val accessMode = txContext.securityContext.mode() allowed.nonEmpty && !accessMode.isOverridden && accessMode.allowsProcedureWith(allowed) } override def callReadOnlyProcedure(name: QualifiedName, args: Seq[Any], allowed: Array[String]) = { val call: KernelProcedureCall = if (shouldElevate(allowed)) - transactionalContext.statement.procedureCallOperations.procedureCallReadOverride(_, _) + txContext.statement.procedureCallOperations.procedureCallReadOverride(_, _) else - transactionalContext.statement.procedureCallOperations.procedureCallRead(_, _) + txContext.statement.procedureCallOperations.procedureCallRead(_, _) callProcedure(name, args, call) } override def callReadWriteProcedure(name: QualifiedName, args: Seq[Any], allowed: Array[String]) = { val call: KernelProcedureCall = if (shouldElevate(allowed)) - transactionalContext.statement.procedureCallOperations.procedureCallWriteOverride(_, _) + txContext.statement.procedureCallOperations.procedureCallWriteOverride(_, _) else - transactionalContext.statement.procedureCallOperations.procedureCallWrite(_, _) + txContext.statement.procedureCallOperations.procedureCallWrite(_, _) callProcedure(name, args, call) } override def callSchemaWriteProcedure(name: QualifiedName, args: Seq[Any], allowed: Array[String]) = { val call: KernelProcedureCall = if (shouldElevate(allowed)) - transactionalContext.statement.procedureCallOperations.procedureCallSchemaOverride(_, _) + txContext.statement.procedureCallOperations.procedureCallSchemaOverride(_, _) else - transactionalContext.statement.procedureCallOperations.procedureCallSchema(_, _) + txContext.statement.procedureCallOperations.procedureCallSchema(_, _) callProcedure(name, args, call) } override def callDbmsProcedure(name: QualifiedName, args: Seq[Any], allowed: Array[String]) = { - callProcedure(name, args, transactionalContext.dbmsOperations.procedureCallDbms(_,_,transactionalContext.securityContext)) + callProcedure(name, args, txContext.dbmsOperations.procedureCallDbms(_,_,txContext.securityContext)) } private def callProcedure(name: QualifiedName, args: Seq[Any], call: KernelProcedureCall) = { @@ -638,9 +638,9 @@ final class TransactionBoundQueryContext(val transactionalContext: Transactional override def callFunction(name: QualifiedName, args: Seq[Any], allowed: Array[String]) = { val call: KernelFunctionCall = if (shouldElevate(allowed)) - transactionalContext.statement.procedureCallOperations.functionCallOverride(_, _) + txContext.statement.procedureCallOperations.functionCallOverride(_, _) else - transactionalContext.statement.procedureCallOperations.functionCall(_, _) + txContext.statement.procedureCallOperations.functionCall(_, _) callFunction(name, args, call) } @@ -688,14 +688,30 @@ final class TransactionBoundQueryContext(val transactionalContext: Transactional override def detachDeleteNode(node: Node): Int = { try { - transactionalContext.statement.dataWriteOperations().nodeDetachDelete(node.getId) + txContext.statement.dataWriteOperations().nodeDetachDelete(node.getId) } catch { case _: exceptions.EntityNotFoundException => 0 // node has been deleted by another transaction, oh well... } } override def assertSchemaWritesAllowed(): Unit = - transactionalContext.statement.schemaWriteOperations() + txContext.statement.schemaWriteOperations() + + override def transactionalContext: QueryTransactionalContext = new QueryTransactionalContext { + override type ReadOps = ReadOperations + + override type DbmsOps = DbmsOperations + + override def commitAndRestartTx(): Unit = txContext.commitAndRestartTx() + + override def readOperations: ReadOps = txContext.tc.readOperations() + + override def isTopLevelTx: Boolean = txContext.isTopLevelTx + + override def dbmsOperations: DbmsOperations = txContext.tc.dbmsOperations() + + override def close(success: Boolean): Unit = txContext.tc.close(success) + } } object TransactionBoundQueryContext { diff --git a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_1/TransactionBoundTokenContext.scala b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_1/TransactionBoundTokenContext.scala index bfa617615c4b7..67a77a2855c29 100644 --- a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_1/TransactionBoundTokenContext.scala +++ b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_1/TransactionBoundTokenContext.scala @@ -19,7 +19,7 @@ */ package org.neo4j.cypher.internal.spi.v3_1 -import org.neo4j.cypher.internal.compiler.v3_2.spi.TokenContext +import org.neo4j.cypher.internal.compiler.v3_1.spi.TokenContext import org.neo4j.kernel.api.Statement import org.neo4j.kernel.api.exceptions.{LabelNotFoundKernelException, PropertyKeyNotFoundException, RelationshipTypeNotFoundException} import org.neo4j.kernel.impl.api.operations.KeyReadOperations diff --git a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_1/codegen/AuxGenerator.scala b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_1/codegen/AuxGenerator.scala index 8ce91e529ad2d..0f2851c5fcd73 100644 --- a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_1/codegen/AuxGenerator.scala +++ b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_1/codegen/AuxGenerator.scala @@ -20,8 +20,8 @@ package org.neo4j.cypher.internal.spi.v3_1.codegen import org.neo4j.codegen.{CodeGenerator, TypeReference} -import org.neo4j.cypher.internal.compiler.v3_2.codegen.ir.expressions.CodeGenType -import org.neo4j.cypher.internal.compiler.v3_2.helpers._ +import org.neo4j.cypher.internal.compiler.v3_1.codegen.ir.expressions.CodeGenType +import org.neo4j.cypher.internal.compiler.v3_1.helpers._ import scala.collection.mutable diff --git a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_1/codegen/GeneratedMethodStructure.scala b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_1/codegen/GeneratedMethodStructure.scala index f84734c4349a1..9bf071832f07f 100644 --- a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_1/codegen/GeneratedMethodStructure.scala +++ b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_1/codegen/GeneratedMethodStructure.scala @@ -28,13 +28,13 @@ import org.neo4j.collection.primitive.hopscotch.LongKeyIntValueTable import org.neo4j.collection.primitive.{PrimitiveLongIntMap, PrimitiveLongIterator, PrimitiveLongObjectMap} import org.neo4j.cypher.internal.codegen.CompiledConversionUtils.CompositeKey import org.neo4j.cypher.internal.codegen._ -import org.neo4j.cypher.internal.compiler.v3_2.ast.convert.commands.DirectionConverter.toGraphDb -import org.neo4j.cypher.internal.compiler.v3_2.codegen._ -import org.neo4j.cypher.internal.compiler.v3_2.codegen.ir.expressions.{BoolType, CodeGenType, FloatType, IntType, ReferenceType} -import org.neo4j.cypher.internal.compiler.v3_2.helpers._ -import org.neo4j.cypher.internal.compiler.v3_2.planDescription.Id -import org.neo4j.cypher.internal.frontend.v3_2.symbols.{CTNode, CTRelationship} -import org.neo4j.cypher.internal.frontend.v3_2.{ParameterNotFoundException, SemanticDirection, symbols} +import org.neo4j.cypher.internal.compiler.v3_1.ast.convert.commands.DirectionConverter.toGraphDb +import org.neo4j.cypher.internal.compiler.v3_1.codegen._ +import org.neo4j.cypher.internal.compiler.v3_1.codegen.ir.expressions.{Parameter => _, _} +import org.neo4j.cypher.internal.compiler.v3_1.helpers._ +import org.neo4j.cypher.internal.compiler.v3_1.planDescription.Id +import org.neo4j.cypher.internal.frontend.v3_1.symbols.{CTNode, CTRelationship} +import org.neo4j.cypher.internal.frontend.v3_1.{ParameterNotFoundException, SemanticDirection, symbols} import org.neo4j.cypher.internal.spi.v3_1.codegen.Methods._ import org.neo4j.cypher.internal.spi.v3_1.codegen.Templates.{createNewInstance, handleKernelExceptions, newRelationshipDataExtractor, tryCatch} import org.neo4j.graphdb.Direction @@ -187,21 +187,16 @@ case class GeneratedMethodStructure(fields: Fields, generator: CodeBlock, aux: A generator.assign(variable, invoke(mathCastToInt, initialValue)) } - - override def decrementCounter(name: String) = { + override def decreaseCounterAndCheckForZero(name: String): Expression = { val local = locals(name) generator.assign(local, subtractInts(local, constant(1))) + + equal(constant(0), local, typeRef[Int]) } - override def checkCounter(name: String, comparator: Comparator, value: Int): Expression = { + override def counterEqualsZero(name: String): Expression = { val local = locals(name) - comparator match { - case Equal => equal(local, constant(value), typeRef[Int]) - case LessThan => lt(local, constant(value), typeRef[Int]) - case LessThanEqual => lte(local, constant(value), typeRef[Int]) - case GreaterThan => gt(local, constant(value), typeRef[Int]) - case GreaterThanEqual => gte(local, constant(value), typeRef[Int]) - } + equal(constant(0), local, typeRef[Int]) } override def setInRow(column: String, value: Expression) = diff --git a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_1/codegen/GeneratedQueryStructure.scala b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_1/codegen/GeneratedQueryStructure.scala index 877ef6d573f28..8ecb76008f917 100644 --- a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_1/codegen/GeneratedQueryStructure.scala +++ b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_1/codegen/GeneratedQueryStructure.scala @@ -26,15 +26,15 @@ import org.neo4j.codegen.CodeGeneratorOption._ import org.neo4j.codegen.TypeReference._ import org.neo4j.codegen.source.{SourceCode, SourceVisitor} import org.neo4j.codegen.{CodeGenerator, _} -import org.neo4j.cypher.internal.compiler.v3_2.codegen._ -import org.neo4j.cypher.internal.compiler.v3_2.codegen.ir.expressions.{CodeGenType, FloatType, IntType, ReferenceType} -import org.neo4j.cypher.internal.compiler.v3_2.executionplan._ -import org.neo4j.cypher.internal.compiler.v3_2.helpers._ -import org.neo4j.cypher.internal.compiler.v3_2.planDescription.{Id, InternalPlanDescription} -import org.neo4j.cypher.internal.compiler.v3_2.planner.CantCompileQueryException -import org.neo4j.cypher.internal.compiler.v3_2.spi.{InternalResultVisitor, QueryContext} -import org.neo4j.cypher.internal.compiler.v3_2.{ExecutionMode, TaskCloser} -import org.neo4j.cypher.internal.frontend.v3_2.symbols +import org.neo4j.cypher.internal.compiler.v3_1.codegen._ +import org.neo4j.cypher.internal.compiler.v3_1.codegen.ir.expressions.{CodeGenType, FloatType, IntType, ReferenceType} +import org.neo4j.cypher.internal.compiler.v3_1.executionplan._ +import org.neo4j.cypher.internal.compiler.v3_1.helpers._ +import org.neo4j.cypher.internal.compiler.v3_1.planDescription.{Id, InternalPlanDescription} +import org.neo4j.cypher.internal.compiler.v3_1.planner.CantCompileQueryException +import org.neo4j.cypher.internal.compiler.v3_1.spi.{InternalResultVisitor, QueryContext} +import org.neo4j.cypher.internal.compiler.v3_1.{ExecutionMode, TaskCloser} +import org.neo4j.cypher.internal.frontend.v3_1.symbols import org.neo4j.kernel.api.ReadOperations import org.neo4j.kernel.impl.core.NodeManager diff --git a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_1/codegen/Methods.scala b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_1/codegen/Methods.scala index d4d1cd6dd82f4..9c4419e57c0c4 100644 --- a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_1/codegen/Methods.scala +++ b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_1/codegen/Methods.scala @@ -24,9 +24,9 @@ import java.util import org.neo4j.collection.primitive.{PrimitiveLongIntMap, PrimitiveLongIterator} import org.neo4j.cypher.internal.codegen.CompiledConversionUtils.CompositeKey import org.neo4j.cypher.internal.codegen._ -import org.neo4j.cypher.internal.compiler.v3_2.codegen.{QueryExecutionEvent, QueryExecutionTracer, ResultRowImpl} -import org.neo4j.cypher.internal.compiler.v3_2.planDescription.Id -import org.neo4j.cypher.internal.compiler.v3_2.spi.{InternalResultRow, InternalResultVisitor} +import org.neo4j.cypher.internal.compiler.v3_1.codegen.{QueryExecutionEvent, QueryExecutionTracer, ResultRowImpl} +import org.neo4j.cypher.internal.compiler.v3_1.planDescription.Id +import org.neo4j.cypher.internal.compiler.v3_1.spi.{InternalResultRow, InternalResultVisitor} import org.neo4j.graphdb.Direction import org.neo4j.helpers.collection.MapUtil import org.neo4j.kernel.api.ReadOperations diff --git a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_1/codegen/Templates.scala b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_1/codegen/Templates.scala index 7115f5d2b7316..1c72a53ff41af 100644 --- a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_1/codegen/Templates.scala +++ b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_1/codegen/Templates.scala @@ -25,12 +25,12 @@ import org.neo4j.codegen.ExpressionTemplate._ import org.neo4j.codegen.MethodReference._ import org.neo4j.codegen._ import org.neo4j.collection.primitive.{Primitive, PrimitiveLongIntMap, PrimitiveLongObjectMap} -import org.neo4j.cypher.internal.compiler.v3_2.codegen._ -import org.neo4j.cypher.internal.compiler.v3_2.executionplan._ -import org.neo4j.cypher.internal.compiler.v3_2.planDescription.InternalPlanDescription -import org.neo4j.cypher.internal.compiler.v3_2.spi.{QueryContext, QueryTransactionalContext} -import org.neo4j.cypher.internal.compiler.v3_2.{ExecutionMode, TaskCloser} -import org.neo4j.cypher.internal.frontend.v3_2.CypherExecutionException +import org.neo4j.cypher.internal.compiler.v3_1.codegen._ +import org.neo4j.cypher.internal.compiler.v3_1.executionplan._ +import org.neo4j.cypher.internal.compiler.v3_1.planDescription.InternalPlanDescription +import org.neo4j.cypher.internal.compiler.v3_1.spi.{QueryContext, QueryTransactionalContext} +import org.neo4j.cypher.internal.compiler.v3_1.{ExecutionMode, TaskCloser} +import org.neo4j.cypher.internal.frontend.v3_1.CypherExecutionException import org.neo4j.graphdb.Direction import org.neo4j.kernel.api.exceptions.KernelException import org.neo4j.kernel.api.{ReadOperations, StatementTokenNameLookup, TokenNameLookup} diff --git a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_0/BidirectionalTraversalMatcher.scala b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_2/BidirectionalTraversalMatcher.scala similarity index 92% rename from community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_0/BidirectionalTraversalMatcher.scala rename to community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_2/BidirectionalTraversalMatcher.scala index 06fc110f76d42..e67bc8eeb4f34 100644 --- a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_0/BidirectionalTraversalMatcher.scala +++ b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_2/BidirectionalTraversalMatcher.scala @@ -17,18 +17,18 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package org.neo4j.cypher.internal.spi.v3_0 +package org.neo4j.cypher.internal.spi.v3_2 import java.util.function.Predicate -import org.neo4j.cypher.internal.compiler.v3_0._ -import org.neo4j.cypher.internal.compiler.v3_0.pipes.matching.{ExpanderStep, TraversalMatcher, TraversalPathExpander} -import org.neo4j.cypher.internal.compiler.v3_0.pipes.{EntityProducer, QueryState} -import org.neo4j.cypher.internal.compiler.v3_0.planDescription.Argument +import org.neo4j.cypher.internal.compiler.v3_2._ +import org.neo4j.cypher.internal.compiler.v3_2.pipes.matching.{ExpanderStep, TraversalMatcher, TraversalPathExpander} +import org.neo4j.cypher.internal.compiler.v3_2.pipes.{EntityProducer, QueryState} +import org.neo4j.cypher.internal.compiler.v3_2.planDescription.Argument +import org.neo4j.graphdb.impl.traversal.StandardBranchCollisionDetector import org.neo4j.graphdb.traversal.{BranchCollisionPolicy, _} import org.neo4j.graphdb.{Node, Path} -import org.neo4j.graphdb.impl.traversal.StandardBranchCollisionDetector -import org.neo4j.kernel.impl.traversal.{MonoDirectionalTraversalDescription, BidirectionalTraversalDescriptionImpl} +import org.neo4j.kernel.impl.traversal.{BidirectionalTraversalDescriptionImpl, MonoDirectionalTraversalDescription} import scala.collection.JavaConverters._ diff --git a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_0/ExceptionTranslatingPlanContext.scala b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_2/ExceptionTranslatingPlanContext.scala similarity index 86% rename from community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_0/ExceptionTranslatingPlanContext.scala rename to community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_2/ExceptionTranslatingPlanContext.scala index aed2e7c8b6be4..bbc96ba8db76e 100644 --- a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_0/ExceptionTranslatingPlanContext.scala +++ b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_2/ExceptionTranslatingPlanContext.scala @@ -17,11 +17,12 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package org.neo4j.cypher.internal.spi.v3_0 +package org.neo4j.cypher.internal.spi.v3_2 -import org.neo4j.cypher.internal.compiler.v3_0.pipes.EntityProducer -import org.neo4j.cypher.internal.compiler.v3_0.pipes.matching.{ExpanderStep, TraversalMatcher} -import org.neo4j.cypher.internal.compiler.v3_0.spi.{GraphStatistics, PlanContext, ProcedureSignature, QualifiedProcedureName} +import org.neo4j.cypher.internal.compiler.v3_2.InternalNotificationLogger +import org.neo4j.cypher.internal.compiler.v3_2.pipes.EntityProducer +import org.neo4j.cypher.internal.compiler.v3_2.pipes.matching.{ExpanderStep, TraversalMatcher} +import org.neo4j.cypher.internal.compiler.v3_2.spi._ import org.neo4j.graphdb.Node import org.neo4j.kernel.api.constraints.UniquenessConstraint import org.neo4j.kernel.api.index.IndexDescriptor @@ -48,9 +49,12 @@ class ExceptionTranslatingPlanContext(inner: PlanContext) extends PlanContext wi () => translateException(innerTxProvider()) } - override def procedureSignature(name: QualifiedProcedureName): ProcedureSignature = + override def procedureSignature(name: QualifiedName): ProcedureSignature = translateException(inner.procedureSignature(name)) + override def functionSignature(name: QualifiedName): Option[UserFunctionSignature] = + translateException(inner.functionSignature(name)) + override def hasIndexRule(labelName: String): Boolean = translateException(inner.hasIndexRule(labelName)) @@ -96,4 +100,7 @@ class ExceptionTranslatingPlanContext(inner: PlanContext) extends PlanContext wi override def getLabelId(labelName: String): Int = translateException(inner.getLabelId(labelName)) + + override def notificationLogger(): InternalNotificationLogger = + translateException(inner.notificationLogger()) } diff --git a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_0/ExceptionTranslationSupport.scala b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_2/ExceptionTranslationSupport.scala similarity index 94% rename from community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_0/ExceptionTranslationSupport.scala rename to community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_2/ExceptionTranslationSupport.scala index b0490aaa9f7a1..1912b152d6f32 100644 --- a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_0/ExceptionTranslationSupport.scala +++ b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_2/ExceptionTranslationSupport.scala @@ -17,9 +17,9 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package org.neo4j.cypher.internal.spi.v3_0 +package org.neo4j.cypher.internal.spi.v3_2 -import org.neo4j.cypher.internal.compiler.v3_0.spi.TokenContext +import org.neo4j.cypher.internal.compiler.v3_2.spi.TokenContext import org.neo4j.cypher.{ConstraintValidationException, CypherExecutionException} import org.neo4j.graphdb.{ConstraintViolationException => KernelConstraintViolationException} import org.neo4j.kernel.api.TokenNameLookup diff --git a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_0/HardcodedGraphStatistics.scala b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_2/HardcodedGraphStatistics.scala similarity index 89% rename from community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_0/HardcodedGraphStatistics.scala rename to community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_2/HardcodedGraphStatistics.scala index ca8b1ad09030a..d24a9949aae16 100644 --- a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_0/HardcodedGraphStatistics.scala +++ b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_2/HardcodedGraphStatistics.scala @@ -17,9 +17,9 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package org.neo4j.cypher.internal.spi.v3_0 +package org.neo4j.cypher.internal.spi.v3_2 //This class should live here, but until we have to touch //disk, let's have it in the compiler. Convenient. case object HardcodedGraphStatistics - extends org.neo4j.cypher.internal.compiler.v3_0.HardcodedGraphStatisticsValues + extends org.neo4j.cypher.internal.compiler.v3_2.HardcodedGraphStatisticsValues diff --git a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_0/MonodirectionalTraversalMatcher.scala b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_2/MonodirectionalTraversalMatcher.scala similarity index 87% rename from community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_0/MonodirectionalTraversalMatcher.scala rename to community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_2/MonodirectionalTraversalMatcher.scala index 18acb05e9cbbc..c60521ba5afc9 100644 --- a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_0/MonodirectionalTraversalMatcher.scala +++ b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_2/MonodirectionalTraversalMatcher.scala @@ -17,12 +17,12 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package org.neo4j.cypher.internal.spi.v3_0 +package org.neo4j.cypher.internal.spi.v3_2 -import org.neo4j.cypher.internal.compiler.v3_0._ -import org.neo4j.cypher.internal.compiler.v3_0.pipes.matching.{ExpanderStep, TraversalMatcher, TraversalPathExpander} -import org.neo4j.cypher.internal.compiler.v3_0.pipes.{EntityProducer, QueryState} -import org.neo4j.cypher.internal.compiler.v3_0.planDescription.Argument +import org.neo4j.cypher.internal.compiler.v3_2._ +import org.neo4j.cypher.internal.compiler.v3_2.pipes.matching.{ExpanderStep, TraversalMatcher, TraversalPathExpander} +import org.neo4j.cypher.internal.compiler.v3_2.pipes.{EntityProducer, QueryState} +import org.neo4j.cypher.internal.compiler.v3_2.planDescription.Argument import org.neo4j.graphdb.traversal._ import org.neo4j.graphdb.{Node, Path} import org.neo4j.graphdb.traversal.Uniqueness @@ -38,7 +38,7 @@ class MonoDirectionalTraversalMatcher(steps: ExpanderStep, start: EntityProducer def reverse() = this } - def baseTraversal(params: ExecutionContext, state:QueryState): TraversalDescription = + def baseTraversal(params: ExecutionContext, state: QueryState): TraversalDescription = new MonoDirectionalTraversalDescription() .uniqueness(Uniqueness.RELATIONSHIP_PATH) .evaluator(new MyEvaluator) diff --git a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_0/TransactionBoundGraphStatistics.scala b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_2/TransactionBoundGraphStatistics.scala similarity index 72% rename from community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_0/TransactionBoundGraphStatistics.scala rename to community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_2/TransactionBoundGraphStatistics.scala index 135dfd6d15604..31359c7f916b1 100644 --- a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_0/TransactionBoundGraphStatistics.scala +++ b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_2/TransactionBoundGraphStatistics.scala @@ -17,14 +17,14 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package org.neo4j.cypher.internal.spi.v3_0 +package org.neo4j.cypher.internal.spi.v3_2 -import org.neo4j.cypher.internal.compiler.v3_0.planner.logical.{Cardinality, Selectivity} -import org.neo4j.cypher.internal.compiler.v3_0.spi.{GraphStatistics, StatisticsCompletingGraphStatistics} -import org.neo4j.cypher.internal.frontend.v3_0.{LabelId, NameId, PropertyKeyId, RelTypeId} +import org.neo4j.cypher.internal.compiler.v3_2.planner.logical.{Cardinality, Selectivity} +import org.neo4j.cypher.internal.compiler.v3_2.spi.{GraphStatistics, StatisticsCompletingGraphStatistics} +import org.neo4j.cypher.internal.frontend.v3_2.{LabelId, NameId, PropertyKeyId, RelTypeId} +import org.neo4j.kernel.api.ReadOperations import org.neo4j.kernel.api.exceptions.index.IndexNotFoundKernelException import org.neo4j.kernel.api.index.IndexDescriptor -import org.neo4j.kernel.api.ReadOperations object TransactionBoundGraphStatistics { def apply(ops: ReadOperations) = new StatisticsCompletingGraphStatistics(new BaseTransactionBoundGraphStatistics(ops)) @@ -35,11 +35,11 @@ object TransactionBoundGraphStatistics { def indexSelectivity(label: LabelId, property: PropertyKeyId): Option[Selectivity] = try { - val indexDescriptor = new IndexDescriptor(label, property) - val labeledNodes = operations.countsForNodeWithoutTxState(label).toDouble + val indexDescriptor = new IndexDescriptor( label, property ) + val labeledNodes = operations.countsForNodeWithoutTxState( label ).toDouble // Probability of any node with the given label, to have a property with a given value - val indexEntrySelectivity = operations.indexUniqueValuesSelectivity(indexDescriptor) + val indexEntrySelectivity = operations.indexUniqueValuesSelectivity( indexDescriptor ) val frequencyOfNodesWithSameValue = 1.0 / indexEntrySelectivity val indexSelectivity = frequencyOfNodesWithSameValue / labeledNodes @@ -51,11 +51,11 @@ object TransactionBoundGraphStatistics { def indexPropertyExistsSelectivity(label: LabelId, property: PropertyKeyId): Option[Selectivity] = try { - val indexDescriptor = new IndexDescriptor(label, property) - val labeledNodes = operations.countsForNodeWithoutTxState(label).toDouble + val indexDescriptor = new IndexDescriptor( label, property ) + val labeledNodes = operations.countsForNodeWithoutTxState( label ).toDouble // Probability of any node with the given label, to have a given property - val indexSize = operations.indexSize(indexDescriptor) + val indexSize = operations.indexSize( indexDescriptor ) val indexSelectivity = indexSize / labeledNodes Selectivity.of(indexSelectivity) @@ -67,21 +67,20 @@ object TransactionBoundGraphStatistics { def nodesWithLabelCardinality(labelId: Option[LabelId]): Cardinality = atLeastOne(operations.countsForNodeWithoutTxState(labelId)) - def cardinalityByLabelsAndRelationshipType(fromLabel: Option[LabelId], relTypeId: Option[RelTypeId], - toLabel: Option[LabelId]): Cardinality = + def cardinalityByLabelsAndRelationshipType(fromLabel: Option[LabelId], relTypeId: Option[RelTypeId], toLabel: Option[LabelId]): Cardinality = atLeastOne(operations.countsForRelationshipWithoutTxState(fromLabel, relTypeId, toLabel)) - } - /** - * Due to the way cardinality calculations work, zero is a bit dangerous, as it cancels out - * any cost that it multiplies with. To avoid this pitfall, we determine that the least count - * available is one, not zero. - */ - private def atLeastOne(count: Double): Cardinality = { - if (count < 1) - Cardinality.SINGLE - else - Cardinality(count) + /** + * Due to the way cardinality calculations work, zero is a bit dangerous, as it cancels out + * any cost that it multiplies with. To avoid this pitfall, we determine that the least count + * available is one, not zero. + */ + private def atLeastOne(count: Double): Cardinality = { + if (count < 1) + Cardinality.SINGLE + else + Cardinality(count) + } } } diff --git a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_0/TransactionBoundPlanContext.scala b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_2/TransactionBoundPlanContext.scala similarity index 71% rename from community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_0/TransactionBoundPlanContext.scala rename to community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_2/TransactionBoundPlanContext.scala index bc8935758029b..a95a457364e2f 100644 --- a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_0/TransactionBoundPlanContext.scala +++ b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_2/TransactionBoundPlanContext.scala @@ -17,16 +17,19 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package org.neo4j.cypher.internal.spi.v3_0 +package org.neo4j.cypher.internal.spi.v3_2 + +import java.util.Optional import org.neo4j.cypher.MissingIndexException import org.neo4j.cypher.internal.LastCommittedTxIdProvider -import org.neo4j.cypher.internal.compiler.v3_0.pipes.EntityProducer -import org.neo4j.cypher.internal.compiler.v3_0.pipes.matching.ExpanderStep -import org.neo4j.cypher.internal.compiler.v3_0.spi._ -import org.neo4j.cypher.internal.frontend.v3_0.symbols.CypherType -import org.neo4j.cypher.internal.frontend.v3_0.{CypherExecutionException, symbols} -import org.neo4j.cypher.internal.spi.TransactionalContextWrapperv3_1 +import org.neo4j.cypher.internal.compiler.v3_2.InternalNotificationLogger +import org.neo4j.cypher.internal.compiler.v3_2.pipes.EntityProducer +import org.neo4j.cypher.internal.compiler.v3_2.pipes.matching.ExpanderStep +import org.neo4j.cypher.internal.compiler.v3_2.spi._ +import org.neo4j.cypher.internal.frontend.v3_2.symbols.CypherType +import org.neo4j.cypher.internal.frontend.v3_2.{CypherExecutionException, symbols} +import org.neo4j.cypher.internal.spi.TransactionalContextWrapperv3_2 import org.neo4j.graphdb.Node import org.neo4j.kernel.api.constraints.UniquenessConstraint import org.neo4j.kernel.api.exceptions.KernelException @@ -34,11 +37,12 @@ import org.neo4j.kernel.api.exceptions.schema.SchemaKernelException import org.neo4j.kernel.api.index.{IndexDescriptor, InternalIndexState} import org.neo4j.kernel.api.proc import org.neo4j.kernel.api.proc.Neo4jTypes.AnyType -import org.neo4j.kernel.api.proc.{ProcedureSignature => KernelProcedureSignature, Mode, QualifiedName, Neo4jTypes} +import org.neo4j.kernel.api.proc.{Neo4jTypes, QualifiedName => KernelQualifiedName} +import org.neo4j.kernel.impl.proc.Neo4jValue import scala.collection.JavaConverters._ -class TransactionBoundPlanContext(tc: TransactionalContextWrapperv3_1) +class TransactionBoundPlanContext(tc: TransactionalContextWrapperv3_2, logger: InternalNotificationLogger) extends TransactionBoundTokenContext(tc.statement) with PlanContext { @Deprecated @@ -128,24 +132,47 @@ class TransactionBoundPlanContext(tc: TransactionalContextWrapperv3_1) val txIdProvider = LastCommittedTxIdProvider(tc.graph) - override def procedureSignature(name: QualifiedProcedureName) = { - val kn = new QualifiedName(name.namespace.asJava, name.name) + override def procedureSignature(name: QualifiedName) = { + val kn = new KernelQualifiedName(name.namespace.asJava, name.name) val ks = tc.statement.readOperations().procedureGet(kn) - val input = ks.inputSignature().asScala.map(s => FieldSignature(s.name(), asCypherType(s.neo4jType()))) - val output = if (ks.isVoid) None else Some(ks.outputSignature().asScala.map(s => FieldSignature(s.name(), asCypherType(s.neo4jType())))) - val mode = asCypherProcMode(ks.mode()) + val input = ks.inputSignature().asScala.map(s => FieldSignature(s.name(), asCypherType(s.neo4jType()), asOption(s.defaultValue()).map(asCypherValue))).toIndexedSeq + val output = if (ks.isVoid) None else Some(ks.outputSignature().asScala.map(s => FieldSignature(s.name(), asCypherType(s.neo4jType()))).toIndexedSeq) + val deprecationInfo = asOption(ks.deprecated()) + val mode = asCypherProcMode(ks.mode(), ks.allowed()) + val description = asOption(ks.description()) + + ProcedureSignature(name, input, output, deprecationInfo, mode, description) + } - ProcedureSignature(name, input, output, mode) + override def functionSignature(name: QualifiedName): Option[UserFunctionSignature] = { + val kn = new KernelQualifiedName(name.namespace.asJava, name.name) + val maybeFunction = tc.statement.readOperations().functionGet(kn) + if (maybeFunction.isPresent) { + val ks = maybeFunction.get + val input = ks.inputSignature().asScala.map(s => FieldSignature(s.name(), asCypherType(s.neo4jType()), asOption(s.defaultValue()).map(asCypherValue))).toIndexedSeq + val output = asCypherType(ks.outputType()) + val deprecationInfo = asOption(ks.deprecated()) + val description = asOption(ks.description()) + + Some(UserFunctionSignature(name, input, output, deprecationInfo, ks.allowed(), description)) + } + else None } - private def asCypherProcMode(mode: Mode): ProcedureAccessMode = mode match { - case proc.Mode.READ_ONLY => ProcedureReadOnlyAccess - case proc.Mode.READ_WRITE => ProcedureReadWriteAccess - case proc.Mode.DBMS => ProcedureDbmsAccess + private def asOption[T](optional: Optional[T]): Option[T] = if (optional.isPresent) Some(optional.get()) else None + + private def asCypherProcMode(mode: proc.Mode, allowed: Array[String]): ProcedureAccessMode = mode match { + case proc.Mode.READ_ONLY => ProcedureReadOnlyAccess(allowed) + case proc.Mode.READ_WRITE => ProcedureReadWriteAccess(allowed) + case proc.Mode.SCHEMA_WRITE => ProcedureSchemaWriteAccess(allowed) + case proc.Mode.DBMS => ProcedureDbmsAccess(allowed) + case _ => throw new CypherExecutionException( "Unable to execute procedure, because it requires an unrecognized execution mode: " + mode.name(), null ) } + private def asCypherValue(neo4jValue: Neo4jValue) = CypherValue(neo4jValue.value, asCypherType(neo4jValue.neo4jType())) + private def asCypherType(neoType: AnyType): CypherType = neoType match { case Neo4jTypes.NTString => symbols.CTString case Neo4jTypes.NTInteger => symbols.CTInteger @@ -153,11 +180,14 @@ class TransactionBoundPlanContext(tc: TransactionalContextWrapperv3_1) case Neo4jTypes.NTNumber => symbols.CTNumber case Neo4jTypes.NTBoolean => symbols.CTBoolean case l: Neo4jTypes.ListType => symbols.CTList(asCypherType(l.innerType())) - case Neo4jTypes.NTMap => symbols.CTMap + case Neo4jTypes.NTPoint => symbols.CTPoint case Neo4jTypes.NTNode => symbols.CTNode case Neo4jTypes.NTRelationship => symbols.CTRelationship case Neo4jTypes.NTPath => symbols.CTPath - case Neo4jTypes.NTPoint => symbols.CTPoint + case Neo4jTypes.NTGeometry => symbols.CTGeometry + case Neo4jTypes.NTMap => symbols.CTMap case Neo4jTypes.NTAny => symbols.CTAny } + + override def notificationLogger(): InternalNotificationLogger = logger } diff --git a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_0/TransactionBoundQueryContext.scala b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_2/TransactionBoundQueryContext.scala similarity index 86% rename from community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_0/TransactionBoundQueryContext.scala rename to community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_2/TransactionBoundQueryContext.scala index bfdd536c1e0e5..550035f5969bc 100644 --- a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_0/TransactionBoundQueryContext.scala +++ b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_2/TransactionBoundQueryContext.scala @@ -17,7 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package org.neo4j.cypher.internal.spi.v3_0 +package org.neo4j.cypher.internal.spi.v3_2 import java.net.URL import java.util.function.Predicate @@ -25,18 +25,18 @@ import java.util.function.Predicate import org.neo4j.collection.RawIterator import org.neo4j.collection.primitive.PrimitiveLongIterator import org.neo4j.collection.primitive.base.Empty.EMPTY_PRIMITIVE_LONG_COLLECTION -import org.neo4j.cypher.internal.compiler.v3_0.MinMaxOrdering.{BY_NUMBER, BY_STRING, BY_VALUE} -import org.neo4j.cypher.internal.compiler.v3_0._ -import org.neo4j.cypher.internal.compiler.v3_0.ast.convert.commands.DirectionConverter.toGraphDb -import org.neo4j.cypher.internal.compiler.v3_0.commands.expressions -import org.neo4j.cypher.internal.compiler.v3_0.commands.expressions.{KernelPredicate, OnlyDirectionExpander, TypeAndDirectionExpander} -import org.neo4j.cypher.internal.compiler.v3_0.helpers.JavaConversionSupport -import org.neo4j.cypher.internal.compiler.v3_0.helpers.JavaConversionSupport._ -import org.neo4j.cypher.internal.compiler.v3_0.pipes.matching.PatternNode -import org.neo4j.cypher.internal.compiler.v3_0.spi._ -import org.neo4j.cypher.internal.frontend.v3_0.{Bound, EntityNotFoundException, FailedIndexException, SemanticDirection, spi => frontend} -import org.neo4j.cypher.internal.spi.v3_0.TransactionBoundQueryContext.IndexSearchMonitor -import org.neo4j.cypher.internal.spi.{BeansAPIRelationshipIterator, TransactionalContextWrapperv3_0} +import org.neo4j.cypher.internal.compiler.v3_2.MinMaxOrdering.{BY_NUMBER, BY_STRING, BY_VALUE} +import org.neo4j.cypher.internal.compiler.v3_2._ +import org.neo4j.cypher.internal.compiler.v3_2.ast.convert.commands.DirectionConverter.toGraphDb +import org.neo4j.cypher.internal.compiler.v3_2.commands.expressions +import org.neo4j.cypher.internal.compiler.v3_2.commands.expressions.{KernelPredicate, OnlyDirectionExpander, TypeAndDirectionExpander} +import org.neo4j.cypher.internal.compiler.v3_2.helpers.JavaConversionSupport +import org.neo4j.cypher.internal.compiler.v3_2.helpers.JavaConversionSupport._ +import org.neo4j.cypher.internal.compiler.v3_2.pipes.matching.PatternNode +import org.neo4j.cypher.internal.compiler.v3_2.spi._ +import org.neo4j.cypher.internal.frontend.v3_2.{Bound, EntityNotFoundException, FailedIndexException, SemanticDirection} +import org.neo4j.cypher.internal.spi.v3_2.TransactionBoundQueryContext.IndexSearchMonitor +import org.neo4j.cypher.internal.spi.{BeansAPIRelationshipIterator, TransactionalContextWrapperv3_2} import org.neo4j.cypher.javacompat.internal.GraphDatabaseCypherService import org.neo4j.cypher.{InternalException, internal} import org.neo4j.graphalgo.impl.path.ShortestPath @@ -51,14 +51,14 @@ import org.neo4j.kernel.api.constraints.{NodePropertyExistenceConstraint, Relati import org.neo4j.kernel.api.exceptions.ProcedureException import org.neo4j.kernel.api.exceptions.schema.{AlreadyConstrainedException, AlreadyIndexedException} import org.neo4j.kernel.api.index.{IndexDescriptor, InternalIndexState} -import org.neo4j.kernel.api.proc.QualifiedName +import org.neo4j.kernel.api.proc.{QualifiedName => KernelQualifiedName} import org.neo4j.kernel.impl.core.NodeManager import org.neo4j.kernel.impl.locking.ResourceTypes import scala.collection.Iterator import scala.collection.JavaConverters._ -final class TransactionBoundQueryContext(val transactionalContext: TransactionalContextWrapperv3_0)(implicit indexSearchMonitor: IndexSearchMonitor) +final class TransactionBoundQueryContext(val transactionalContext: TransactionalContextWrapperv3_2)(implicit indexSearchMonitor: IndexSearchMonitor) extends TransactionBoundTokenContext(transactionalContext.statement) with QueryContext { type EntityAccessor = NodeManager @@ -290,14 +290,6 @@ final class TransactionBoundQueryContext(val transactionalContext: Transactional override def nodeIsDense(node: Long): Boolean = transactionalContext.statement.readOperations().nodeIsDense(node) - override def detachDeleteNode(node: Node): Int = - try { - transactionalContext.statement.dataWriteOperations().nodeDetachDelete(node.getId) - } catch { - case _: exceptions.EntityNotFoundException => 0 - // node has been deleted by another transaction, oh well... - } - class NodeOperations extends BaseOperations[Node] { override def delete(obj: Node) { try { @@ -307,20 +299,8 @@ final class TransactionBoundQueryContext(val transactionalContext: Transactional } } - def propertyKeyIds(id: Long): Iterator[Int] = try { - // use the following when bumping 3.0.x dependency - // JavaConversionSupport.asScalaENFXSafe(tc.statement.readOperations().nodeGetPropertyKeys(id)) - new Iterator[Int] { - val inner = transactionalContext.statement.readOperations().nodeGetPropertyKeys(id) - - override def hasNext: Boolean = inner.hasNext - - override def next(): Int = try { - inner.next() - } catch { - case _: org.neo4j.kernel.api.exceptions.EntityNotFoundException => null.asInstanceOf[Int] - } - } + override def propertyKeyIds(id: Long): Iterator[Int] = try { + JavaConversionSupport.asScalaENFXSafe(transactionalContext.statement.readOperations().nodeGetPropertyKeys(id)) } catch { case _: exceptions.EntityNotFoundException => Iterator.empty } @@ -342,7 +322,7 @@ final class TransactionBoundQueryContext(val transactionalContext: Transactional } override def removeProperty(id: Long, propertyKeyId: Int) { - try { + try { transactionalContext.statement.dataWriteOperations().nodeRemoveProperty(id, propertyKeyId) } catch { case _: exceptions.EntityNotFoundException => //ignore @@ -351,7 +331,7 @@ final class TransactionBoundQueryContext(val transactionalContext: Transactional override def setProperty(id: Long, propertyKeyId: Int, value: Any) { try { - transactionalContext.statement.dataWriteOperations().nodeSetProperty(id, properties.Property.property(propertyKeyId, value) ) + transactionalContext.statement.dataWriteOperations().nodeSetProperty(id, properties.Property.property(propertyKeyId, value) ) } catch { case _: exceptions.EntityNotFoundException => //ignore } @@ -395,19 +375,7 @@ final class TransactionBoundQueryContext(val transactionalContext: Transactional } override def propertyKeyIds(id: Long): Iterator[Int] = try { - // use the following when bumping the cypher 3.0.x version - //JavaConversionSupport.asScalaENFXSafe(statement.readOperations().relationshipGetPropertyKeys(id)) - new Iterator[Int] { - val inner = transactionalContext.statement.readOperations().relationshipGetPropertyKeys(id) - - override def hasNext: Boolean = inner.hasNext - - override def next(): Int = try { - inner.next() - } catch { - case _: org.neo4j.kernel.api.exceptions.EntityNotFoundException => null.asInstanceOf[Int] - } - } + asScalaENFXSafe(transactionalContext.statement.readOperations().relationshipGetPropertyKeys(id)) } catch { case _: exceptions.EntityNotFoundException => Iterator.empty } @@ -616,26 +584,73 @@ final class TransactionBoundQueryContext(val transactionalContext: Transactional pathFinder.findAllPaths(left, right).iterator().asScala } - override def callReadOnlyProcedure(name: QualifiedProcedureName, args: Seq[Any]) = - callProcedure(name, args, transactionalContext.statement.procedureCallOperations().procedureCallRead) + type KernelProcedureCall = (KernelQualifiedName, Array[AnyRef]) => RawIterator[Array[AnyRef], ProcedureException] + type KernelFunctionCall = (KernelQualifiedName, Array[AnyRef]) => AnyRef - override def callReadWriteProcedure(name: QualifiedProcedureName, args: Seq[Any]) = - callProcedure(name, args, transactionalContext.statement.procedureCallOperations().procedureCallWrite) + private def shouldElevate(allowed: Array[String]): Boolean = { + // We have to be careful with elevation, since we cannot elevate permissions in a nested procedure call + // above the original allowed procedure mode. We enforce this by checking if mode is already an overridden mode. + val accessMode = transactionalContext.securityContext.mode() + allowed.nonEmpty && !accessMode.isOverridden && accessMode.allowsProcedureWith(allowed) + } - override def callDbmsProcedure(name: QualifiedProcedureName, args: Seq[Any]) = + override def callReadOnlyProcedure(name: QualifiedName, args: Seq[Any], allowed: Array[String]) = { + val call: KernelProcedureCall = + if (shouldElevate(allowed)) + transactionalContext.statement.procedureCallOperations.procedureCallReadOverride(_, _) + else + transactionalContext.statement.procedureCallOperations.procedureCallRead(_, _) + callProcedure(name, args, call) + } + + override def callReadWriteProcedure(name: QualifiedName, args: Seq[Any], allowed: Array[String]) = { + val call: KernelProcedureCall = + if (shouldElevate(allowed)) + transactionalContext.statement.procedureCallOperations.procedureCallWriteOverride(_, _) + else + transactionalContext.statement.procedureCallOperations.procedureCallWrite(_, _) + callProcedure(name, args, call) + } + + override def callSchemaWriteProcedure(name: QualifiedName, args: Seq[Any], allowed: Array[String]) = { + val call: KernelProcedureCall = + if (shouldElevate(allowed)) + transactionalContext.statement.procedureCallOperations.procedureCallSchemaOverride(_, _) + else + transactionalContext.statement.procedureCallOperations.procedureCallSchema(_, _) + callProcedure(name, args, call) + } + + override def callDbmsProcedure(name: QualifiedName, args: Seq[Any], allowed: Array[String]) = { callProcedure(name, args, transactionalContext.dbmsOperations.procedureCallDbms(_,_,transactionalContext.securityContext)) + } - private def callProcedure(name: QualifiedProcedureName, args: Seq[Any], - call: (QualifiedName, Array[AnyRef]) => RawIterator[Array[AnyRef], ProcedureException]) = { - val kn = new QualifiedName(name.namespace.asJava, name.name) + private def callProcedure(name: QualifiedName, args: Seq[Any], call: KernelProcedureCall) = { + val kn = new KernelQualifiedName(name.namespace.asJava, name.name) val toArray = args.map(_.asInstanceOf[AnyRef]).toArray - val read: RawIterator[Array[AnyRef], ProcedureException] = call(kn, toArray) + val read = call(kn, toArray) new scala.Iterator[Array[AnyRef]] { override def hasNext: Boolean = read.hasNext override def next(): Array[AnyRef] = read.next } } + override def callFunction(name: QualifiedName, args: Seq[Any], allowed: Array[String]) = { + val call: KernelFunctionCall = + if (shouldElevate(allowed)) + transactionalContext.statement.procedureCallOperations.functionCallOverride(_, _) + else + transactionalContext.statement.procedureCallOperations.functionCall(_, _) + callFunction(name, args, call) + } + + private def callFunction(name: QualifiedName, args: Seq[Any], + call: KernelFunctionCall) = { + val kn = new KernelQualifiedName(name.namespace.asJava, name.name) + val toArray = args.map(_.asInstanceOf[AnyRef]).toArray + call(kn, toArray) + } + override def isGraphKernelResultValue(v: Any): Boolean = internal.isGraphKernelResultValue(v) private def buildPathFinder(depth: Int, expander: expressions.Expander, pathPredicate: KernelPredicate[Path], @@ -670,6 +685,17 @@ final class TransactionBoundQueryContext(val transactionalContext: Transactional else null } } + + override def detachDeleteNode(node: Node): Int = { + try { + transactionalContext.statement.dataWriteOperations().nodeDetachDelete(node.getId) + } catch { + case _: exceptions.EntityNotFoundException => 0 // node has been deleted by another transaction, oh well... + } + } + + override def assertSchemaWritesAllowed(): Unit = + transactionalContext.statement.schemaWriteOperations() } object TransactionBoundQueryContext { diff --git a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_0/TransactionBoundTokenContext.scala b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_2/TransactionBoundTokenContext.scala similarity index 96% rename from community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_0/TransactionBoundTokenContext.scala rename to community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_2/TransactionBoundTokenContext.scala index 8613cb9f0349f..aa7072469c680 100644 --- a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_0/TransactionBoundTokenContext.scala +++ b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_2/TransactionBoundTokenContext.scala @@ -17,9 +17,9 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package org.neo4j.cypher.internal.spi.v3_0 +package org.neo4j.cypher.internal.spi.v3_2 -import org.neo4j.cypher.internal.compiler.v3_0.spi.TokenContext +import org.neo4j.cypher.internal.compiler.v3_2.spi.TokenContext import org.neo4j.kernel.api.Statement import org.neo4j.kernel.api.exceptions.{LabelNotFoundKernelException, PropertyKeyNotFoundException, RelationshipTypeNotFoundException} import org.neo4j.kernel.impl.api.operations.KeyReadOperations diff --git a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_2/codegen/AuxGenerator.scala b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_2/codegen/AuxGenerator.scala new file mode 100644 index 0000000000000..da0a8c05e6c53 --- /dev/null +++ b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_2/codegen/AuxGenerator.scala @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2002-2016 "Neo Technology," + * Network Engine for Objects in Lund AB [http://neotechnology.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.cypher.internal.spi.v3_2.codegen + +import org.neo4j.codegen.{CodeGenerator, TypeReference} +import org.neo4j.cypher.internal.compiler.v3_2.codegen.ir.expressions.CodeGenType +import org.neo4j.cypher.internal.compiler.v3_2.helpers._ + +import scala.collection.mutable + +class AuxGenerator(val packageName: String, val generator: CodeGenerator) { + + import GeneratedQueryStructure.lowerType + + private val types: scala.collection.mutable.Map[Map[String, CodeGenType], TypeReference] = mutable.Map.empty + private var nameId = 0 + + + def typeReference(structure: Map[String, CodeGenType]): TypeReference = { + types.getOrElseUpdate(structure, using(generator.generateClass(packageName, newName())) { clazz => + structure.foreach { + case (fieldName, fieldType: CodeGenType) => clazz.field(lowerType(fieldType), fieldName) + } + clazz.handle() + }) + } + + private def newName() = { + val name = "ValueType" + nameId + nameId += 1 + name + } +} diff --git a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_2/codegen/Fields.scala b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_2/codegen/Fields.scala new file mode 100644 index 0000000000000..0602e7a5c3c20 --- /dev/null +++ b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_2/codegen/Fields.scala @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2002-2016 "Neo Technology," + * Network Engine for Objects in Lund AB [http://neotechnology.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.cypher.internal.spi.v3_2.codegen + +import org.neo4j.codegen.{FieldReference, MethodReference} + +case class Fields(closer: FieldReference, + ro: FieldReference, + entityAccessor: FieldReference, + executionMode: FieldReference, + description: FieldReference, + tracer: FieldReference, + params: FieldReference, + closeable: FieldReference, + success: MethodReference, + close: MethodReference) diff --git a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_2/codegen/GeneratedMethodStructure.scala b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_2/codegen/GeneratedMethodStructure.scala new file mode 100644 index 0000000000000..5d0f30f61351b --- /dev/null +++ b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_2/codegen/GeneratedMethodStructure.scala @@ -0,0 +1,777 @@ +/* + * Copyright (c) 2002-2016 "Neo Technology," + * Network Engine for Objects in Lund AB [http://neotechnology.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.cypher.internal.spi.v3_2.codegen + +import java.util + +import org.neo4j.codegen.Expression.{not, or, _} +import org.neo4j.codegen.MethodReference.methodReference +import org.neo4j.codegen._ +import org.neo4j.collection.primitive.hopscotch.LongKeyIntValueTable +import org.neo4j.collection.primitive.{PrimitiveLongIntMap, PrimitiveLongIterator, PrimitiveLongObjectMap} +import org.neo4j.cypher.internal.codegen.CompiledConversionUtils.CompositeKey +import org.neo4j.cypher.internal.codegen._ +import org.neo4j.cypher.internal.compiler.v3_2.ast.convert.commands.DirectionConverter.toGraphDb +import org.neo4j.cypher.internal.compiler.v3_2.codegen._ +import org.neo4j.cypher.internal.compiler.v3_2.codegen.ir.expressions.{BoolType, CodeGenType, FloatType, IntType, ReferenceType} +import org.neo4j.cypher.internal.compiler.v3_2.helpers._ +import org.neo4j.cypher.internal.compiler.v3_2.planDescription.Id +import org.neo4j.cypher.internal.frontend.v3_2.symbols.{CTNode, CTRelationship} +import org.neo4j.cypher.internal.frontend.v3_2.{ParameterNotFoundException, SemanticDirection, symbols} +import org.neo4j.cypher.internal.spi.v3_2.codegen.Methods._ +import org.neo4j.cypher.internal.spi.v3_2.codegen.Templates.{createNewInstance, handleKernelExceptions, newRelationshipDataExtractor, tryCatch} +import org.neo4j.graphdb.Direction +import org.neo4j.kernel.api.index.IndexDescriptor +import org.neo4j.kernel.impl.api.RelationshipDataExtractor +import org.neo4j.kernel.impl.api.store.RelationshipIterator + +import scala.collection.mutable + +case class GeneratedMethodStructure(fields: Fields, generator: CodeBlock, aux: AuxGenerator, tracing: Boolean = true, + events: List[String] = List.empty, + locals: mutable.Map[String, LocalVariable] = mutable.Map.empty) + (implicit context: CodeGenContext) + extends MethodStructure[Expression] { + + import GeneratedQueryStructure._ + import TypeReference.parameterizedType + + private case class HashTable(valueType: TypeReference, listType: TypeReference, tableType: TypeReference, + get: MethodReference, put: MethodReference, add: MethodReference) + + private implicit class RichTableType(tableType: RecordingJoinTableType) { + + def extractHashTable(): HashTable = tableType match { + case LongToListTable(structure, localMap) => + // compute the participating types + val valueType = aux.typeReference(structure) + val listType = parameterizedType(classOf[util.ArrayList[_]], valueType) + val tableType = parameterizedType(classOf[PrimitiveLongObjectMap[_]], valueType) + // the methods we use on those types + val get = methodReference(tableType, typeRef[Object], "get", typeRef[Long]) + val put = methodReference(tableType, typeRef[Object], "put", typeRef[Long], typeRef[Object]) + val add = methodReference(listType, typeRef[Boolean], "add", typeRef[Object]) + + HashTable(valueType, listType, tableType, get, put, add) + + case LongsToListTable(structure, localMap) => + // compute the participating types + val valueType = aux.typeReference(structure) + val listType = parameterizedType(classOf[util.ArrayList[_]], valueType) + val tableType = parameterizedType(classOf[util.HashMap[_, _]], typeRef[CompositeKey], valueType) + // the methods we use on those types + val get = methodReference(tableType, typeRef[Object], "get", typeRef[Object]) + val put = methodReference(tableType, typeRef[Object], "put", typeRef[Object], typeRef[Object]) + val add = methodReference(listType, typeRef[Boolean], "add", typeRef[Object]) + HashTable(valueType, listType, tableType, get, put, add) + } + } + + override def nextNode(targetVar: String, iterVar: String) = + generator.assign(typeRef[Long], targetVar, invoke(generator.load(iterVar), nextLong)) + + override def createRelExtractor(relVar: String) = + generator.assign(typeRef[RelationshipDataExtractor], relExtractor(relVar), newRelationshipDataExtractor) + + + override def nextRelationshipAndNode(toNodeVar: String, iterVar: String, direction: SemanticDirection, + fromNodeVar: String, + relVar: String) = { + val extractor = relExtractor(relVar) + val start = invoke(generator.load(extractor), startNode) + val end = invoke(generator.load(extractor), endNode) + + generator.expression( + pop( + invoke(generator.load(iterVar), relationshipVisit, + invoke(generator.load(iterVar), fetchNextRelationship), + generator.load(extractor)))) + generator.assign(typeRef[Long], toNodeVar, toGraphDb(direction) match { + case Direction.INCOMING => start + case Direction.OUTGOING => end + case Direction.BOTH => ternary(equal(start, generator.load(fromNodeVar), typeRef[Long]), end, start) + }) + generator.assign(typeRef[Long], relVar, invoke(generator.load(extractor), getRelationship)) + } + + private def relExtractor(relVar: String) = s"${relVar}Extractor" + + override def nextRelationship(iterVar: String, ignored: SemanticDirection, relVar: String) = { + val extractor = relExtractor(relVar) + generator.expression( + pop( + invoke(generator.load(iterVar), relationshipVisit, + invoke(generator.load(iterVar), fetchNextRelationship), + generator.load(extractor)))) + generator.assign(typeRef[Long], relVar, invoke(generator.load(extractor), getRelationship)) + } + + override def allNodesScan(iterVar: String) = + generator.assign(typeRef[PrimitiveLongIterator], iterVar, invoke(readOperations, nodesGetAll)) + + override def labelScan(iterVar: String, labelIdVar: String) = + generator.assign(typeRef[PrimitiveLongIterator], iterVar, + invoke(readOperations, nodesGetForLabel, generator.load(labelIdVar))) + + override def lookupLabelId(labelIdVar: String, labelName: String) = + generator.assign(typeRef[Int], labelIdVar, + invoke(readOperations, labelGetForName, constant(labelName))) + + override def lookupRelationshipTypeId(typeIdVar: String, typeName: String) = + generator.assign(typeRef[Int], typeIdVar, invoke(readOperations, relationshipTypeGetForName, constant(typeName))) + + override def hasNextNode(iterVar: String) = + invoke(generator.load(iterVar), hasNextLong) + + override def hasNextRelationship(iterVar: String) = + invoke(generator.load(iterVar), hasMoreRelationship) + + override def whileLoop(test: Expression)(block: MethodStructure[Expression] => Unit) = + using(generator.whileLoop(test)) { body => + block(copy(generator = body)) + } + + override def forEach(varName: String, codeGenType: CodeGenType, iterable: Expression) + (block: MethodStructure[Expression] => Unit) = + using(generator.forEach(Parameter.param(lowerType(codeGenType), varName), iterable)) { body => + block(copy(generator = body)) + } + + override def ifStatement(test: Expression)(block: (MethodStructure[Expression]) => Unit) = { + using(generator.ifStatement(test)) { body => + block(copy(generator = body)) + } + } + + override def ifNotStatement(test: Expression)(block: (MethodStructure[Expression]) => Unit) = { + using(generator.ifNotStatement(test)) { body => + block(copy(generator = body)) + } + } + + override def ternaryOperator(test: Expression, onTrue: Expression, onFalse: Expression): Expression = + ternary(test, onTrue, onFalse) + + override def returnSuccessfully() { + //close all outstanding events + for (event <- events) { + generator.expression( + invoke(generator.load(event), + method[QueryExecutionEvent, Unit]("close"))) + } + generator.expression(invoke(generator.self(), fields.success)) + generator.expression(invoke(generator.self(), fields.close)) + generator.returns() + } + + override def declareCounter(name: String, initialValue: Expression): Unit = { + val variable = generator.declare(typeRef[Int], name) + locals += (name -> variable) + generator.assign(variable, invoke(mathCastToInt, initialValue)) + } + + + override def decrementCounter(name: String) = { + val local = locals(name) + generator.assign(local, subtractInts(local, constant(1))) + } + + override def checkCounter(name: String, comparator: Comparator, value: Int): Expression = { + val local = locals(name) + comparator match { + case Equal => equal(local, constant(value), typeRef[Int]) + case LessThan => lt(local, constant(value), typeRef[Int]) + case LessThanEqual => lte(local, constant(value), typeRef[Int]) + case GreaterThan => gt(local, constant(value), typeRef[Int]) + case GreaterThanEqual => gte(local, constant(value), typeRef[Int]) + } + } + + override def setInRow(column: String, value: Expression) = + generator.expression(invoke(resultRow, set, constant(column), value)) + + override def visitorAccept() = tryCatch(generator) { onSuccess => + using( + onSuccess.ifNotStatement( + invoke(onSuccess.load("visitor"), + visit, onSuccess.load("row")))) { body => + // NOTE: we are in this if-block if the visitor decided to terminate early (by returning false) + //close all outstanding events + for (event <- events) { + body.expression(invoke(generator.load(event), + method[QueryExecutionEvent, Unit]("close"))) + } + body.expression(invoke(body.self(), fields.success)) + body.expression(invoke(body.self(), fields.close)) + body.returns() + } + }(exception = param[Throwable]("e")) { onError => + onError.expression(invoke(onError.self(), fields.close)) + onError.throwException(onError.load("e")) + } + + + override def materializeNode(nodeIdVar: String) = + invoke(nodeManager, newNodeProxyById, generator.load(nodeIdVar)) + + override def node(nodeIdVar: String) = createNewInstance(typeRef[NodeIdWrapper], (typeRef[Long], generator.load(nodeIdVar))) + + override def nullablePrimitive(varName: String, codeGenType: CodeGenType, onSuccess: Expression) = codeGenType match { + case CodeGenType(CTNode, IntType) | CodeGenType(CTRelationship, IntType) => + ternary( + equal(nullValue(codeGenType), generator.load(varName), lowerType(codeGenType)), + nullValue(codeGenType), + onSuccess) + case _ => ternaryOnNull(generator.load(varName), constant(null), onSuccess) + } + + override def nullableReference(varName: String, codeGenType: CodeGenType, onSuccess: Expression) = codeGenType match { + case CodeGenType(CTNode, IntType) | CodeGenType(CTRelationship, IntType) => + ternary( + equal(nullValue(codeGenType), generator.load(varName), lowerType(codeGenType)), + constant(null), + onSuccess) + case _ => ternaryOnNull(generator.load(varName), constant(null), onSuccess) + } + + override def materializeRelationship(relIdVar: String) = + invoke(nodeManager, newRelationshipProxyById, generator.load(relIdVar)) + + override def relationship(relIdVar: String) = createNewInstance(typeRef[RelationshipIdWrapper], + (typeRef[Long], generator.load(relIdVar))) + + override def trace[V](planStepId: String)(block: MethodStructure[Expression] => V) = if (!tracing) block(this) + else { + val eventName = s"event_$planStepId" + generator.assign(typeRef[QueryExecutionEvent], eventName, traceEvent(planStepId)) + val result = block(copy(events = eventName :: events, generator = generator)) + generator.expression(invoke(generator.load(eventName), method[QueryExecutionEvent, Unit]("close"))) + result + } + + private def traceEvent(planStepId: String) = + invoke(tracer, executeOperator, + get(FieldReference.staticField(generator.owner(), typeRef[Id], planStepId))) + + override def incrementDbHits() = if (tracing) generator.expression(invoke(loadEvent, Methods.dbHit)) + + override def incrementRows() = if (tracing) generator.expression(invoke(loadEvent, Methods.row)) + + private def loadEvent = generator.load(events.headOption.getOrElse(throw new IllegalStateException("no current trace event"))) + + override def expectParameter(key: String, variableName: String) = { + using( + generator.ifNotStatement(invoke(params, mapContains, constant(key)))) { block => + block.throwException(parameterNotFoundException(key)) + } + generator.assign(typeRef[Object], variableName, invoke(loadParameter, + invoke(params, mapGet, constantExpression(key)))) + } + + override def constantExpression(value: Object) = value match { + case n: java.lang.Byte => constant(n.toLong) + case n: java.lang.Short => constant(n.toLong) + case n: java.lang.Character => constant(n.toLong) + case n: java.lang.Integer => constant(n.toLong) + case n: java.lang.Float => constant(n.toDouble) + case _ => constant(value) + } + + override def notExpression(value: Expression): Expression = not(value) + + override def threeValuedNotExpression(value: Expression): Expression = invoke(Methods.not, value) + + override def threeValuedEqualsExpression(lhs: Expression, rhs: Expression) = invoke(Methods.ternaryEquals, lhs, rhs) + + override def equalityExpression(lhs: Expression, rhs: Expression, codeGenType: CodeGenType) = + if (codeGenType.isPrimitive) equal(lhs, rhs, lowerType(codeGenType)) + else invoke(lhs, Methods.equals, rhs) + + override def orExpression(lhs: Expression, rhs: Expression) = or(lhs, rhs) + + override def threeValuedOrExpression(lhs: Expression, rhs: Expression) = invoke(Methods.or, lhs, rhs) + + override def markAsNull(varName: String, codeGenType: CodeGenType) = + generator.assign(lowerType(codeGenType), varName, nullValue(codeGenType)) + + + override def isNull(varName: String, codeGenType: CodeGenType) = + equal(nullValue(codeGenType), generator.load(varName), lowerType(codeGenType)) + + override def notNull(varName: String, codeGenType: CodeGenType) = not(isNull(varName, codeGenType)) + + override def box(expression: Expression, cType: CodeGenType) = cType match { + case CodeGenType(symbols.CTBoolean, BoolType) => invoke(Methods.boxBoolean, expression) + case CodeGenType(symbols.CTInteger, IntType) => invoke(Methods.boxLong, expression) + case CodeGenType(symbols.CTFloat, FloatType) => invoke(Methods.boxDouble, expression) + case _ => expression + } + + override def unbox(expression: Expression, cType: CodeGenType) = cType match { + case c if c.isPrimitive => expression + case CodeGenType(symbols.CTBoolean, ReferenceType) => invoke(expression, Methods.unboxBoolean) + case CodeGenType(symbols.CTInteger, ReferenceType) => invoke(expression, Methods.unboxLong) + case CodeGenType(symbols.CTFloat, ReferenceType) => invoke(expression, Methods.unboxDouble) + case CodeGenType(symbols.CTNode, ReferenceType) => invoke(expression, Methods.unboxNode) + case CodeGenType(symbols.CTRelationship, ReferenceType) => invoke(expression, Methods.unboxRel) + case _ => throw new IllegalStateException(s"$expression cannot be unboxed") + } + + override def toFloat(expression: Expression) = toDouble(expression) + + override def nodeGetAllRelationships(iterVar: String, nodeVar: String, direction: SemanticDirection) = { + val local = generator.declare(typeRef[RelationshipIterator], iterVar) + handleKernelExceptions(generator, fields.ro, fields.close) { body => + body.assign(local, invoke(readOperations, Methods.nodeGetAllRelationships, body.load(nodeVar), dir(direction))) + } + } + + override def nodeGetRelationships(iterVar: String, nodeVar: String, direction: SemanticDirection, + typeVars: Seq[String]) = { + val local = generator.declare(typeRef[RelationshipIterator], iterVar) + handleKernelExceptions(generator, fields.ro, fields.close) { body => + body.assign(local, invoke(readOperations, Methods.nodeGetRelationships, + body.load(nodeVar), dir(direction), + newArray(typeRef[Int], typeVars.map(body.load): _*))) + } + } + + override def connectingRelationships(iterVar: String, fromNode: String, direction: SemanticDirection, + toNode: String) = { + val local = generator.declare(typeRef[RelationshipIterator], iterVar) + handleKernelExceptions(generator, fields.ro, fields.close) { body => + body.assign(local, invoke(Methods.allConnectingRelationships, + readOperations, body.load(fromNode), dir(direction), + body.load(toNode))) + } + } + + override def connectingRelationships(iterVar: String, fromNode: String, direction: SemanticDirection, + typeVars: Seq[String], toNode: String) = { + val local = generator.declare(typeRef[RelationshipIterator], iterVar) + handleKernelExceptions(generator, fields.ro, fields.close) { body => + body.assign(local, invoke(Methods.connectingRelationships, readOperations, body.load(fromNode), dir(direction), + body.load(toNode), + newArray(typeRef[Int], typeVars.map(body.load): _*))) + } + } + + override def loadVariable(varName: String) = generator.load(varName) + + override def add(lhs: Expression, rhs: Expression) = math(Methods.mathAdd, lhs, rhs) + + override def subtract(lhs: Expression, rhs: Expression) = math(Methods.mathSub, lhs, rhs) + + override def multiply(lhs: Expression, rhs: Expression) = math(Methods.mathMul, lhs, rhs) + + override def divide(lhs: Expression, rhs: Expression) = math(Methods.mathDiv, lhs, rhs) + + override def modulus(lhs: Expression, rhs: Expression) = math(Methods.mathMod, lhs, rhs) + + private def math(method: MethodReference, lhs: Expression, rhs: Expression): Expression = + invoke(method, lhs, rhs) + + private def readOperations = get(generator.self(), fields.ro) + + private def nodeManager = get(generator.self(), fields.entityAccessor) + + private def resultRow = generator.load("row") + + private def tracer = get(generator.self(), fields.tracer) + + private def params = get(generator.self(), fields.params) + + private def parameterNotFoundException(key: String) = + invoke(newInstance(typeRef[ParameterNotFoundException]), + MethodReference.constructorReference(typeRef[ParameterNotFoundException], typeRef[String]), + constant(s"Expected a parameter named $key")) + + private def dir(dir: SemanticDirection): Expression = dir match { + case SemanticDirection.INCOMING => Templates.incoming + case SemanticDirection.OUTGOING => Templates.outgoing + case SemanticDirection.BOTH => Templates.both + } + + override def asList(values: Seq[Expression]) = Templates.asList[Object](values) + + override def toSet(value: Expression) = + createNewInstance(typeRef[util.HashSet[Object]], (typeRef[util.Collection[_]], value)) + + override def castToCollection(value: Expression) = invoke(Methods.toCollection, value) + + override def asMap(map: Map[String, Expression]) = { + invoke(Methods.createMap, + newArray(typeRef[Object], map.flatMap { + case (key, value) => Seq(constant(key), value) + }.toSeq: _*)) + } + + override def invokeMethod(resultType: JoinTableType, resultVar: String, methodName: String) + (block: MethodStructure[Expression] => Unit) = { + val returnType: TypeReference = joinTableType(resultType) + generator.assign(returnType, resultVar, + invoke(generator.self(), methodReference(generator.owner(), returnType, methodName))) + using(generator.classGenerator().generateMethod(returnType, methodName)) { body => + block(copy(generator = body, events = List.empty)) + body.returns(body.load(resultVar)) + } + } + + override def allocateProbeTable(tableVar: String, tableType: JoinTableType) = + generator.assign(joinTableType(tableType), tableVar, allocate(tableType)) + + private def joinTableType(resultType: JoinTableType): TypeReference = { + val returnType = resultType match { + case LongToCountTable => typeRef[PrimitiveLongIntMap] + case LongsToCountTable => TypeReference + .parameterizedType(classOf[util.HashMap[_, _]], classOf[CompositeKey], classOf[java.lang.Integer]) + case LongToListTable(structure, _) => parameterizedType(classOf[PrimitiveLongObjectMap[_]], + parameterizedType( + classOf[util.ArrayList[_]], + aux.typeReference(structure))) + case LongsToListTable(structure, _) => TypeReference + .parameterizedType(classOf[util.HashMap[_, _]], typeRef[CompositeKey], + parameterizedType(classOf[util.ArrayList[_]], aux.typeReference(structure))) + } + returnType + } + + private def allocate(resultType: JoinTableType): Expression = resultType match { + case LongToCountTable => Templates.newCountingMap + case LongToListTable(_, _) => Templates.newLongObjectMap + case LongsToCountTable => createNewInstance(joinTableType(LongsToCountTable)) + case typ: LongsToListTable => createNewInstance(joinTableType(typ)) + } + + override def updateProbeTableCount(tableVar: String, tableType: CountingJoinTableType, + keyVars: Seq[String]) = tableType match { + case LongToCountTable => + assert(keyVars.size == 1) + val keyVar = keyVars.head + val countName = context.namer.newVarName() + generator.assign(typeRef[Int], countName, + invoke(generator.load(tableVar), countingTableGet, generator.load(keyVar))) + generator.expression( + pop( + invoke(generator.load(tableVar), countingTablePut, generator.load(keyVar), + ternary( + equal(generator.load(countName), get(staticField[LongKeyIntValueTable, Int]("NULL")), typeRef[Int]), + constant(1), + addInts(generator.load(countName), constant(1)))))) + + case LongsToCountTable => + val countName = context.namer.newVarName() + val keyName = context.namer.newVarName() + generator.assign(typeRef[CompositeKey], keyName, + invoke(compositeKey, + newArray(typeRef[Long], keyVars.map(generator.load): _*))) + generator.assign(typeRef[java.lang.Integer], countName, + cast(typeRef[java.lang.Integer], + invoke(generator.load(tableVar), countingTableCompositeKeyGet, + generator.load(keyName)) + )) + generator.expression( + pop( + invoke(generator.load(tableVar), countingTableCompositeKeyPut, + generator.load(keyName), + ternaryOnNull(generator.load(countName), + invoke(boxInteger, + constant(1)), invoke(boxInteger, + addInts( + invoke(generator.load(countName), + unboxInteger), + constant(1))))))) + } + + override def probe(tableVar: String, tableType: JoinTableType, keyVars: Seq[String]) + (block: MethodStructure[Expression] => Unit) = tableType match { + case LongToCountTable => + assert(keyVars.size == 1) + val keyVar = keyVars.head + val times = generator.declare(typeRef[Int], context.namer.newVarName()) + generator.assign(times, invoke(generator.load(tableVar), countingTableGet, generator.load(keyVar))) + using(generator.whileLoop(gt(times, constant(0), typeRef[Int]))) { body => + block(copy(generator = body)) + body.assign(times, subtractInts(times, constant(1))) + } + case LongsToCountTable => + val times = generator.declare(typeRef[Int], context.namer.newVarName()) + val intermediate = generator.declare(typeRef[java.lang.Integer], context.namer.newVarName()) + generator.assign(intermediate, + cast(typeRef[Integer], + invoke(generator.load(tableVar), + countingTableCompositeKeyGet, + invoke(compositeKey, + newArray(typeRef[Long], + keyVars.map(generator.load): _*))))) + generator.assign(times, + ternaryOnNull( + intermediate, + constant(-1), + invoke(intermediate, unboxInteger))) + + using(generator.whileLoop(gt(times, constant(0), typeRef[Int]))) { body => + block(copy(generator = body)) + body.assign(times, subtractInts(times, constant(1))) + } + + case tableType@LongToListTable(structure, localVars) => + assert(keyVars.size == 1) + val keyVar = keyVars.head + + val hashTable = tableType.extractHashTable() + // generate the code + val list = generator.declare(hashTable.listType, context.namer.newVarName()) + val elementName = context.namer.newVarName() + generator.assign(list, invoke(generator.load(tableVar), hashTable.get, generator.load(keyVar))) + using(generator.ifNonNullStatement(list)) { onTrue => + using(onTrue.forEach(Parameter.param(hashTable.valueType, elementName), list)) { forEach => + localVars.foreach { + case (l, f) => + val fieldType = lowerType(structure(f)) + forEach.assign(fieldType, l, get(forEach.load(elementName), + field(structure, structure(f), f))) + } + block(copy(generator = forEach)) + } + } + + case tableType@LongsToListTable(structure, localVars) => + val hashTable = tableType.extractHashTable() + val list = generator.declare(hashTable.listType, context.namer.newVarName()) + val elementName = context.namer.newVarName() + + generator.assign(list, + cast(hashTable.listType, + invoke(generator.load(tableVar), hashTable.get, + invoke(compositeKey, + newArray(typeRef[Long], + keyVars.map(generator.load): _*)) + ))) + using(generator.ifNonNullStatement(list)) { onTrue => + using(onTrue.forEach(Parameter.param(hashTable.valueType, elementName), list)) { forEach => + localVars.foreach { + case (l, f) => + val fieldType = lowerType(structure(f)) + forEach.assign(fieldType, l, get(forEach.load(elementName), + field(structure, structure(f), f))) + } + block(copy(generator = forEach)) + } + } + } + + override def putField(structure: Map[String, CodeGenType], value: Expression, fieldType: CodeGenType, + fieldName: String, + localVar: String) = { + generator.put(value, field(structure, fieldType, fieldName), generator.load(localVar)) + } + + override def updateProbeTable(structure: Map[String, CodeGenType], tableVar: String, + tableType: RecordingJoinTableType, + keyVars: Seq[String], element: Expression) = tableType match { + case _: LongToListTable => + assert(keyVars.size == 1) + val keyVar = keyVars.head + val hashTable = tableType.extractHashTable() + // generate the code + val listName = context.namer.newVarName() + val list = generator.declare(hashTable.listType, listName) // ProbeTable list; + // list = tableVar.get(keyVar); + generator.assign(list, + cast(hashTable.listType, + invoke( + generator.load(tableVar), hashTable.get, + generator.load(keyVar)))) + using(generator.ifNullStatement(list)) { onTrue => // if (null == list) + // list = new ListType(); + onTrue.assign(list, createNewInstance(hashTable.listType)) + onTrue.expression( + // tableVar.put(keyVar, list); + pop( + invoke( + generator.load(tableVar), hashTable.put, generator.load(keyVar), generator.load(listName)))) + } + // list.add( element ); + generator.expression( + pop( + invoke(list, hashTable.add, element)) + ) + + case _: LongsToListTable => + val hashTable = tableType.extractHashTable() + // generate the code + val listName = context.namer.newVarName() + val keyName = context.namer.newVarName() + val list = generator.declare(hashTable.listType, listName) // ProbeTable list; + generator.assign(typeRef[CompositeKey], keyName, + invoke(compositeKey, + newArray(typeRef[Long], keyVars.map(generator.load): _*))) + // list = tableVar.get(keyVar); + generator.assign(list, + cast(hashTable.listType, + invoke(generator.load(tableVar), hashTable.get, generator.load(keyName)))) + using(generator.ifNullStatement(generator.load(listName))) { onTrue => // if (null == list) + // list = new ListType(); + onTrue.assign(list, createNewInstance(hashTable.listType)) + // tableVar.put(keyVar, list); + onTrue.expression( + pop( + invoke(generator.load(tableVar), hashTable.put, generator.load(keyName), + generator.load(listName)))) + } + // list.add( element ); + generator.expression( + pop( + invoke(list, hashTable.add, element))) + } + + override def declareProperty(propertyVar: String) = { + val localVariable = generator.declare(typeRef[Object], propertyVar) + locals += (propertyVar -> localVariable) + generator.assign(localVariable, constant(null)) + } + + override def declare(varName: String, codeGenType: CodeGenType) = { + val localVariable = generator.declare(lowerType(codeGenType), varName) + locals += (varName -> localVariable) + generator.assign(localVariable, nullValue(codeGenType)) + } + + override def hasLabel(nodeVar: String, labelVar: String, predVar: String) = { + val local = locals(predVar) + + handleKernelExceptions(generator, fields.ro, fields.close) { inner => + val invoke = Expression.invoke(readOperations, nodeHasLabel, inner.load(nodeVar), inner.load(labelVar)) + inner.assign(local, invoke) + generator.load(predVar) + } + } + + override def relType(relVar: String, typeVar: String) = { + val variable = locals(typeVar) + val typeOfRel = invoke(generator.load(relExtractor(relVar)), typeOf) + handleKernelExceptions(generator, fields.ro, fields.close) { inner => + val res = invoke(readOperations, relationshipTypeGetName, typeOfRel) + inner.assign(variable, res) + generator.load(variable.name()) + } + } + + override def projectVariable(variableName: String, expression: Expression) = { + // java.lang.Object is an ok type for result variables because we only put them into result row + val resultType = typeRef[Object] + val localVariable = generator.declare(resultType, variableName) + generator.assign(localVariable, expression) + } + + override def declareFlag(name: String, initialValue: Boolean) = { + val localVariable = generator.declare(typeRef[Boolean], name) + locals += (name -> localVariable) + generator.assign(localVariable, constant(initialValue)) + } + + override def updateFlag(name: String, newValue: Boolean) = { + generator.assign(locals(name), constant(newValue)) + } + + override def declarePredicate(name: String) = { + locals += (name -> generator.declare(typeRef[Boolean], name)) + } + + override def nodeGetPropertyForVar(nodeIdVar: String, propIdVar: String, propValueVar: String) = { + val local = locals(propValueVar) + handleKernelExceptions(generator, fields.ro, fields.close) { body => + body.assign(local, invoke(readOperations, nodeGetProperty, body.load(nodeIdVar), body.load(propIdVar))) + } + } + + override def nodeGetPropertyById(nodeIdVar: String, propId: Int, propValueVar: String) = { + val local = locals(propValueVar) + handleKernelExceptions(generator, fields.ro, fields.close) { body => + body.assign(local, invoke(readOperations, nodeGetProperty, body.load(nodeIdVar), constant(propId))) + } + } + + override def nodeIdSeek(nodeIdVar: String, expression: Expression)(block: MethodStructure[Expression] => Unit) = { + generator.assign(typeRef[Long], nodeIdVar, invoke(Methods.mathCastToLong, expression)) + using(generator.ifStatement( + gt(generator.load(nodeIdVar), constant(-1L), typeRef[Long]), + invoke(readOperations, nodeExists, generator.load(nodeIdVar)) + )) { ifBody => + block(copy(generator = ifBody)) + } + } + + override def relationshipGetPropertyForVar(relIdVar: String, propIdVar: String, propValueVar: String) = { + val local = locals(propValueVar) + handleKernelExceptions(generator, fields.ro, fields.close) { body => + body.assign(local, + invoke(readOperations, relationshipGetProperty, body.load(relIdVar), body.load(propIdVar))) + } + } + + override def relationshipGetPropertyById(relIdVar: String, propId: Int, propValueVar: String) = { + val local = locals(propValueVar) + handleKernelExceptions(generator, fields.ro, fields.close) { body => + body.assign(local, invoke(readOperations, relationshipGetProperty, body.load(relIdVar), constant(propId))) + } + } + + override def lookupPropertyKey(propName: String, propIdVar: String) = + generator.assign(typeRef[Int], propIdVar, invoke(readOperations, propertyKeyGetForName, constant(propName))) + + override def newIndexDescriptor(descriptorVar: String, labelVar: String, propKeyVar: String) = { + generator.assign(typeRef[IndexDescriptor], descriptorVar, + createNewInstance(typeRef[IndexDescriptor], (typeRef[Int], generator.load(labelVar)), + (typeRef[Int], generator.load(propKeyVar))) + ) + } + + override def indexSeek(iterVar: String, descriptorVar: String, value: Expression) = { + val local = generator.declare(typeRef[PrimitiveLongIterator], iterVar) + handleKernelExceptions(generator, fields.ro, fields.close) { body => + body.assign(local, invoke(readOperations, nodesGetFromIndexLookup, generator.load(descriptorVar), value)) + } + } + + override def indexUniqueSeek(nodeVar: String, descriptorVar: String, value: Expression) = { + val local = generator.declare(typeRef[Long], nodeVar) + handleKernelExceptions(generator, fields.ro, fields.close) { body => + body.assign(local, + invoke(readOperations, nodeGetUniqueFromIndexLookup, generator.load(descriptorVar), value)) + } + } + + override def coerceToBoolean(propertyExpression: Expression): Expression = + invoke(coerceToPredicate, propertyExpression) + + override def newTableValue(targetVar: String, structure: Map[String, CodeGenType]) = { + val valueType = aux.typeReference(structure) + generator.assign(valueType, targetVar, createNewInstance(valueType)) + generator.load(targetVar) + } + + private def field(structure: Map[String, CodeGenType], fieldType: CodeGenType, fieldName: String) = + FieldReference.field(aux.typeReference(structure), lowerType(fieldType), fieldName) +} + + + diff --git a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_2/codegen/GeneratedQueryStructure.scala b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_2/codegen/GeneratedQueryStructure.scala new file mode 100644 index 0000000000000..de98d89493c68 --- /dev/null +++ b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_2/codegen/GeneratedQueryStructure.scala @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2002-2016 "Neo Technology," + * Network Engine for Objects in Lund AB [http://neotechnology.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.cypher.internal.spi.v3_2.codegen + +import java.lang.reflect.Modifier +import java.util + +import org.neo4j.codegen.CodeGeneratorOption._ +import org.neo4j.codegen.TypeReference._ +import org.neo4j.codegen.source.{SourceCode, SourceVisitor} +import org.neo4j.codegen.{CodeGenerator, _} +import org.neo4j.cypher.internal.compiler.v3_2.codegen._ +import org.neo4j.cypher.internal.compiler.v3_2.codegen.ir.expressions.{CodeGenType, FloatType, IntType, ReferenceType} +import org.neo4j.cypher.internal.compiler.v3_2.executionplan._ +import org.neo4j.cypher.internal.compiler.v3_2.helpers._ +import org.neo4j.cypher.internal.compiler.v3_2.planDescription.{Id, InternalPlanDescription} +import org.neo4j.cypher.internal.compiler.v3_2.planner.CantCompileQueryException +import org.neo4j.cypher.internal.compiler.v3_2.spi.{InternalResultVisitor, QueryContext} +import org.neo4j.cypher.internal.compiler.v3_2.{ExecutionMode, TaskCloser} +import org.neo4j.cypher.internal.frontend.v3_2.symbols +import org.neo4j.kernel.api.ReadOperations +import org.neo4j.kernel.impl.core.NodeManager + +object GeneratedQueryStructure extends CodeStructure[GeneratedQuery] { + + import Expression.{constant, invoke, newInstance} + import MethodReference.constructorReference + + case class GeneratedQueryStructureResult(query: GeneratedQuery, source: Option[(String, String)]) + extends CodeStructureResult[GeneratedQuery] + + private def createGenerator(conf: CodeGenConfiguration, source: (Option[(String, String)]) => Unit) = { + val mode = conf.mode match { + case SourceCodeMode => SourceCode.SOURCECODE + case ByteCodeMode => SourceCode.BYTECODE + } + val option = if (conf.saveSource) new SourceVisitor { + override protected def visitSource(reference: TypeReference, + sourceCode: CharSequence) = source(Some(reference.name(), sourceCode.toString)) + } else { + source(None) + BLANK_OPTION + } + + try { + CodeGenerator.generateCode(classOf[CodeStructure[_]].getClassLoader, mode, option) + } catch { + case e: Exception => throw new CantCompileQueryException(e.getMessage, e) + } + } + + class SourceSaver extends ((Option[(String, String)]) => Unit) { + + private var _source: Option[(String, String)] = None + + override def apply(v1: Option[(String, String)]) = _source = v1 + + def source: Option[(String, String)] = _source + } + + override def generateQuery(className: String, columns: Seq[String], operatorIds: Map[String, Id], + conf: CodeGenConfiguration) + (block: MethodStructure[_] => Unit)(implicit codeGenContext: CodeGenContext) = { + + val sourceSaver = new SourceSaver + val generator = createGenerator(conf, sourceSaver) + val execution = using( + generator.generateClass(conf.packageName, className + "Execution", typeRef[GeneratedQueryExecution], + typeRef[SuccessfulCloseable])) { clazz => + // fields + val fields = Fields( + closer = clazz.field(typeRef[TaskCloser], "closer"), + ro = clazz.field(typeRef[ReadOperations], "ro"), + entityAccessor = clazz.field(typeRef[NodeManager], "nodeManager"), + executionMode = clazz.field(typeRef[ExecutionMode], "executionMode"), + description = clazz.field(typeRef[Provider[InternalPlanDescription]], "description"), + tracer = clazz.field(typeRef[QueryExecutionTracer], "tracer"), + params = clazz.field(typeRef[util.Map[String, Object]], "params"), + closeable = clazz.field(typeRef[SuccessfulCloseable], "closeable"), + success = clazz.generate(Templates.SUCCESS), + close = clazz.generate(Templates.CLOSE)) + // the "COLUMNS" static field + clazz.staticField(typeRef[util.List[String]], "COLUMNS", Templates.asList[String]( + columns.map(key => constant(key)))) + + // the operator id fields + operatorIds.keys.foreach { opId => + clazz.staticField(typeRef[Id], opId) + } + + // simple methods + clazz.generate(Templates.CONSTRUCTOR) + clazz.generate(Templates.SET_SUCCESSFUL_CLOSEABLE) + clazz.generate(Templates.EXECUTION_MODE) + clazz.generate(Templates.EXECUTION_PLAN_DESCRIPTION) + clazz.generate(Templates.JAVA_COLUMNS) + + using(clazz.generate(MethodDeclaration.method(typeRef[Unit], "accept", + Parameter.param(parameterizedType(classOf[InternalResultVisitor[_]], + typeParameter("E")), "visitor")). + parameterizedWith("E", extending(typeRef[Exception])). + throwsException(typeParameter("E")))) { method => + method.assign(typeRef[ResultRowImpl], "row", Templates.newResultRow) + block(GeneratedMethodStructure(fields, method, new AuxGenerator(conf.packageName, generator))) + method.expression(invoke(method.self(), fields.success)) + method.expression(invoke(method.self(), fields.close)) + } + clazz.handle() + } + val query = using(generator.generateClass(conf.packageName, className, typeRef[GeneratedQuery])) { clazz => + using(clazz.generateMethod(typeRef[GeneratedQueryExecution], "execute", + param[TaskCloser]("closer"), + param[QueryContext]("queryContext"), + param[ExecutionMode]("executionMode"), + param[Provider[InternalPlanDescription]]("description"), + param[QueryExecutionTracer]("tracer"), + param[util.Map[String, Object]]("params"))) { execute => + execute.returns( + invoke( + newInstance(execution), + constructorReference(execution, + typeRef[TaskCloser], + typeRef[QueryContext], + typeRef[ExecutionMode], + typeRef[Provider[InternalPlanDescription]], + typeRef[QueryExecutionTracer], + typeRef[util.Map[String, Object]]), + execute.load("closer"), + execute.load("queryContext"), + execute.load("executionMode"), + execute.load("description"), + execute.load("tracer"), + execute.load("params"))) + } + clazz.handle() + }.newInstance().asInstanceOf[GeneratedQuery] + val clazz: Class[_] = execution.loadClass() + operatorIds.foreach { + case (key, id) => setStaticField(clazz, key, id) + } + + GeneratedQueryStructureResult(query, sourceSaver.source) + } + + def method[O <: AnyRef, R](name: String, params: TypeReference*) + (implicit owner: Manifest[O], returns: Manifest[R]): MethodReference = + MethodReference.methodReference(typeReference(owner), typeReference(returns), name, Modifier.PUBLIC, params: _*) + + def staticField[O <: AnyRef, R](name: String)(implicit owner: Manifest[O], fieldType: Manifest[R]): FieldReference = + FieldReference.staticField(typeReference(owner), typeReference(fieldType), name) + + def param[T <: AnyRef](name: String)(implicit manifest: Manifest[T]): Parameter = + Parameter.param(typeReference(manifest), name) + + def typeRef[T](implicit manifest: Manifest[T]): TypeReference = typeReference(manifest) + + def typeReference(manifest: Manifest[_]): TypeReference = { + val arguments = manifest.typeArguments + val base = TypeReference.typeReference(manifest.runtimeClass) + if (arguments.nonEmpty) { + TypeReference.parameterizedType(base, arguments.map(typeReference): _*) + } else { + base + } + } + + def lowerType(cType: CodeGenType): TypeReference = cType match { + case CodeGenType(symbols.CTNode, IntType) => typeRef[Long] + case CodeGenType(symbols.CTRelationship, IntType) => typeRef[Long] + case CodeGenType(symbols.CTInteger, IntType) => typeRef[Long] + case CodeGenType(symbols.CTFloat, FloatType) => typeRef[Double] + case CodeGenType(symbols.CTString, ReferenceType) => typeRef[String] + case _ => typeRef[Object] + } + + def nullValue(cType: CodeGenType) = cType match { + case CodeGenType(symbols.CTNode, IntType) => constant(-1L) + case CodeGenType(symbols.CTRelationship, IntType) => constant(-1L) + case _ => constant(null) + } +} \ No newline at end of file diff --git a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_2/codegen/Methods.scala b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_2/codegen/Methods.scala new file mode 100644 index 0000000000000..cc8f28fcdce0b --- /dev/null +++ b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_2/codegen/Methods.scala @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2002-2016 "Neo Technology," + * Network Engine for Objects in Lund AB [http://neotechnology.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.cypher.internal.spi.v3_2.codegen + +import java.util + +import org.neo4j.collection.primitive.{PrimitiveLongIntMap, PrimitiveLongIterator} +import org.neo4j.cypher.internal.codegen.CompiledConversionUtils.CompositeKey +import org.neo4j.cypher.internal.codegen._ +import org.neo4j.cypher.internal.compiler.v3_2.codegen.{QueryExecutionEvent, QueryExecutionTracer, ResultRowImpl} +import org.neo4j.cypher.internal.compiler.v3_2.planDescription.Id +import org.neo4j.cypher.internal.compiler.v3_2.spi.{InternalResultRow, InternalResultVisitor} +import org.neo4j.graphdb.Direction +import org.neo4j.helpers.collection.MapUtil +import org.neo4j.kernel.api.ReadOperations +import org.neo4j.kernel.api.index.IndexDescriptor +import org.neo4j.kernel.impl.api.store.RelationshipIterator +import org.neo4j.kernel.impl.api.{RelationshipDataExtractor, RelationshipVisitor} +import org.neo4j.kernel.impl.core.{NodeManager, NodeProxy, RelationshipProxy} + +object Methods { + + import GeneratedQueryStructure.{method, typeRef} + + val countingTablePut = method[PrimitiveLongIntMap, Int]("put", typeRef[Long], typeRef[Int]) + val countingTableCompositeKeyPut = method[util.HashMap[CompositeKey, Integer], Object]("put", typeRef[Object], typeRef[Object]) + val countingTableGet = method[PrimitiveLongIntMap, Int]("get", typeRef[Long]) + val countingTableCompositeKeyGet = method[util.HashMap[CompositeKey, Integer], Object]("get", typeRef[Object]) + val compositeKey = method[CompiledConversionUtils, CompositeKey]("compositeKey", typeRef[Array[Long]]) + val hasNextLong = method[PrimitiveLongIterator, Boolean]("hasNext") + val hasMoreRelationship = method[RelationshipIterator, Boolean]("hasNext") + val createMap = method[MapUtil, util.Map[String, Object]]("map", typeRef[Array[Object]]) + val format = method[String, String]("format", typeRef[String], typeRef[Array[Object]]) + val relationshipVisit = method[RelationshipIterator, Boolean]("relationshipVisit", typeRef[Long], typeRef[RelationshipVisitor[RuntimeException]]) + val getRelationship = method[RelationshipDataExtractor, Long]("relationship") + val startNode = method[RelationshipDataExtractor, Long]("startNode") + val endNode = method[RelationshipDataExtractor, Long]("endNode") + val typeOf = method[RelationshipDataExtractor, Int]("type") + val nodeGetAllRelationships = method[ReadOperations, RelationshipIterator]("nodeGetRelationships", typeRef[Long], typeRef[Direction]) + val nodeGetRelationships = method[ReadOperations, RelationshipIterator]("nodeGetRelationships", typeRef[Long], typeRef[Direction], typeRef[Array[Int]]) + val allConnectingRelationships = method[CompiledExpandUtils, RelationshipIterator]("connectingRelationships", typeRef[ReadOperations], typeRef[Long], typeRef[Direction], typeRef[Long]) + val connectingRelationships = method[CompiledExpandUtils, RelationshipIterator]("connectingRelationships", typeRef[ReadOperations], typeRef[Long], typeRef[Direction], typeRef[Long], typeRef[Array[Int]]) + val mathAdd = method[CompiledMathHelper, Object]("add", typeRef[Object], typeRef[Object]) + val mathSub = method[CompiledMathHelper, Object]("subtract", typeRef[Object], typeRef[Object]) + val mathMul = method[CompiledMathHelper, Object]("multiply", typeRef[Object], typeRef[Object]) + val mathDiv = method[CompiledMathHelper, Object]("divide", typeRef[Object], typeRef[Object]) + val mathMod = method[CompiledMathHelper, Object]("modulo", typeRef[Object], typeRef[Object]) + val mathCastToInt = method[CompiledMathHelper, Int]("transformToInt", typeRef[Object]) + val mathCastToLong = method[CompiledMathHelper, Long]("transformToLong", typeRef[Object]) + val mapGet = method[util.Map[String, Object], Object]("get", typeRef[Object]) + val mapContains = method[util.Map[String, Object], Boolean]("containsKey", typeRef[Object]) + val labelGetForName = method[ReadOperations, Int]("labelGetForName", typeRef[String]) + val propertyKeyGetForName = method[ReadOperations, Int]("propertyKeyGetForName", typeRef[String]) + val coerceToPredicate = method[CompiledConversionUtils, Boolean]("coerceToPredicate", typeRef[Object]) + val toCollection = method[CompiledConversionUtils, java.util.Collection[Object]]("toCollection", typeRef[Object]) + val ternaryEquals = method[CompiledConversionUtils, java.lang.Boolean]("equals", typeRef[Object], typeRef[Object]) + val equals = method[Object, Boolean]("equals", typeRef[Object]) + val or = method[CompiledConversionUtils, java.lang.Boolean]("or", typeRef[Object], typeRef[Object]) + val not = method[CompiledConversionUtils, java.lang.Boolean]("not", typeRef[Object]) + val loadParameter = method[CompiledConversionUtils, java.lang.Object]("loadParameter", typeRef[Object]) + val relationshipTypeGetForName = method[ReadOperations, Int]("relationshipTypeGetForName", typeRef[String]) + val relationshipTypeGetName = method[ReadOperations, String]("relationshipTypeGetName", typeRef[Int]) + val nodeExists = method[ReadOperations, Boolean]("nodeExists", typeRef[Long]) + val nodesGetAll = method[ReadOperations, PrimitiveLongIterator]("nodesGetAll") + val nodeGetProperty = method[ReadOperations, Object]("nodeGetProperty", typeRef[Long], typeRef[Int]) + val nodesGetFromIndexLookup = method[ReadOperations, PrimitiveLongIterator]("nodesGetFromIndexSeek", typeRef[IndexDescriptor], typeRef[Object]) + val nodeGetUniqueFromIndexLookup = method[ReadOperations, Long]("nodeGetFromUniqueIndexSeek", typeRef[IndexDescriptor], typeRef[Object]) + val relationshipGetProperty = method[ReadOperations, Object]("relationshipGetProperty", typeRef[Long], typeRef[Int]) + val nodesGetForLabel = method[ReadOperations, PrimitiveLongIterator]("nodesGetForLabel", typeRef[Int]) + val nodeHasLabel = method[ReadOperations, Boolean]("nodeHasLabel", typeRef[Long], typeRef[Int]) + val nextLong = method[PrimitiveLongIterator, Long]("next") + val fetchNextRelationship = method[RelationshipIterator, Long]("next") + val newNodeProxyById = method[NodeManager, NodeProxy]("newNodeProxyById", typeRef[Long]) + val newRelationshipProxyById = method[NodeManager, RelationshipProxy]("newRelationshipProxyById", typeRef[Long]) + val nodeId = method[NodeIdWrapper, Long]("id") + val relId = method[RelationshipIdWrapper, Long]("id") + val set = method[ResultRowImpl, Unit]("set", typeRef[String], typeRef[Object]) + val visit = method[InternalResultVisitor[_], Boolean]("visit", typeRef[InternalResultRow]) + val executeOperator = method[QueryExecutionTracer, QueryExecutionEvent]("executeOperator", typeRef[Id]) + val dbHit = method[QueryExecutionEvent, Unit]("dbHit") + val row = method[QueryExecutionEvent, Unit]("row") + val boxBoolean = method[java.lang.Boolean, java.lang.Boolean]("valueOf", typeRef[Boolean]) + val boxLong = method[java.lang.Long, java.lang.Long]("valueOf", typeRef[Long]) + val boxInteger = method[java.lang.Integer, java.lang.Integer]("valueOf", typeRef[Int]) + val boxDouble = method[java.lang.Double, java.lang.Double]("valueOf", typeRef[Double]) + val unboxInteger = method[java.lang.Integer, Int]("intValue") + val unboxBoolean = method[java.lang.Boolean, Boolean]("booleanValue") + val unboxLong = method[java.lang.Long, Long]("longValue") + val unboxDouble = method[java.lang.Double, Double]("doubleValue") + val unboxNode = method[NodeProxy, Long]("getNodeId") + val unboxRel = method[RelationshipProxy, Long]("getRelationshipId") +} diff --git a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_2/codegen/Templates.scala b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_2/codegen/Templates.scala new file mode 100644 index 0000000000000..eebc93f5f4474 --- /dev/null +++ b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_2/codegen/Templates.scala @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2002-2016 "Neo Technology," + * Network Engine for Objects in Lund AB [http://neotechnology.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.cypher.internal.spi.v3_2.codegen +import java.util +import java.util.function.Consumer + +import org.neo4j.codegen.ExpressionTemplate._ +import org.neo4j.codegen.MethodReference._ +import org.neo4j.codegen._ +import org.neo4j.collection.primitive.{Primitive, PrimitiveLongIntMap, PrimitiveLongObjectMap} +import org.neo4j.cypher.internal.compiler.v3_2.codegen._ +import org.neo4j.cypher.internal.compiler.v3_2.executionplan._ +import org.neo4j.cypher.internal.compiler.v3_2.planDescription.InternalPlanDescription +import org.neo4j.cypher.internal.compiler.v3_2.spi.{QueryContext, QueryTransactionalContext} +import org.neo4j.cypher.internal.compiler.v3_2.{ExecutionMode, TaskCloser} +import org.neo4j.cypher.internal.frontend.v3_2.CypherExecutionException +import org.neo4j.graphdb.Direction +import org.neo4j.kernel.api.exceptions.KernelException +import org.neo4j.kernel.api.{ReadOperations, StatementTokenNameLookup, TokenNameLookup} +import org.neo4j.kernel.impl.api.RelationshipDataExtractor +import org.neo4j.kernel.impl.core.NodeManager + +/** + * Contains common code generation constructs. + */ +object Templates { + + import GeneratedQueryStructure.{method, param, staticField, typeRef} + + def createNewInstance(valueType: TypeReference, args: (TypeReference,Expression)*): Expression = { + val argTypes = args.map(_._1) + val argExpression = args.map(_._2) + Expression.invoke(Expression.newInstance(valueType), + MethodReference.constructorReference(valueType, argTypes: _*), argExpression:_*) + } + + val newLongObjectMap = Expression.invoke(method[Primitive, PrimitiveLongObjectMap[_]]("longObjectMap")) + val newCountingMap = Expression.invoke(method[Primitive, PrimitiveLongIntMap]("longIntMap")) + + def asList[T](values: Seq[Expression])(implicit manifest: Manifest[T]): Expression = Expression.invoke( + methodReference(typeRef[util.Arrays], typeRef[util.List[T]], "asList", typeRef[Array[Object]]), + Expression.newArray(typeRef[T], values: _*)) + + def handleKernelExceptions[V](generate: CodeBlock, ro: FieldReference, close: MethodReference) + (block: CodeBlock => V): V = { + var result = null.asInstanceOf[V] + + generate.tryCatch(new Consumer[CodeBlock] { + override def accept(body: CodeBlock) = { + result = block(body) + } + }, new Consumer[CodeBlock]() { + override def accept(handle: CodeBlock) = { + handle.expression(Expression.invoke(handle.self(), close)) + handle.throwException(Expression.invoke( + Expression.newInstance(typeRef[CypherExecutionException]), + MethodReference.constructorReference(typeRef[CypherExecutionException], typeRef[String], typeRef[Throwable]), + Expression + .invoke(handle.load("e"), method[KernelException, String]("getUserMessage", typeRef[TokenNameLookup]), + Expression.invoke( + Expression.newInstance(typeRef[StatementTokenNameLookup]), + MethodReference + .constructorReference(typeRef[StatementTokenNameLookup], typeRef[ReadOperations]), + Expression.get(handle.self(), ro))), handle.load("e") + )) + } + }, param[KernelException]("e")) + + result + } + + def tryCatch(generate: CodeBlock)(tryBlock :CodeBlock => Unit)(exception: Parameter)(catchBlock :CodeBlock => Unit): Unit = { + generate.tryCatch(new Consumer[CodeBlock] { + override def accept(body: CodeBlock) = tryBlock(body) + }, new Consumer[CodeBlock]() { + override def accept(handle: CodeBlock) = catchBlock(handle) + }, exception) + } + + val incoming = Expression.get(staticField[Direction, Direction](Direction.INCOMING.name())) + val outgoing = Expression.get(staticField[Direction, Direction](Direction.OUTGOING.name())) + val both = Expression.get(staticField[Direction, Direction](Direction.BOTH.name())) + val newResultRow = Expression + .invoke(Expression.newInstance(typeRef[ResultRowImpl]), + MethodReference.constructorReference(typeRef[ResultRowImpl])) + val newRelationshipDataExtractor = Expression + .invoke(Expression.newInstance(typeRef[RelationshipDataExtractor]), + MethodReference.constructorReference(typeRef[RelationshipDataExtractor])) + + val CONSTRUCTOR = MethodTemplate.constructor( + param[TaskCloser]("closer"), + param[QueryContext]("queryContext"), + param[ExecutionMode]("executionMode"), + param[Provider[InternalPlanDescription]]("description"), + param[QueryExecutionTracer]("tracer"), + + param[util.Map[String, Object]]("params")). + invokeSuper(). + put(self(), typeRef[TaskCloser], "closer", load("closer")). + put(self(), typeRef[ReadOperations], "ro", + cast(classOf[ReadOperations], invoke( + invoke(load("queryContext"), method[QueryContext, QueryTransactionalContext]("transactionalContext")), + method[QueryTransactionalContext, Object]("readOperations")))). + put(self(), typeRef[ExecutionMode], "executionMode", load("executionMode")). + put(self(), typeRef[Provider[InternalPlanDescription]], "description", load("description")). + put(self(), typeRef[QueryExecutionTracer], "tracer", load("tracer")). + put(self(), typeRef[util.Map[String, Object]], "params", load("params")). + put(self(), typeRef[NodeManager], "nodeManager", + cast(typeRef[NodeManager], + invoke(load("queryContext"), method[QueryContext, Object]("entityAccessor")))). + build() + + val SET_SUCCESSFUL_CLOSEABLE = MethodTemplate.method(typeRef[Unit], "setSuccessfulCloseable", + param[SuccessfulCloseable]("closeable")). + put(self(), typeRef[SuccessfulCloseable], "closeable", load("closeable")). + build() + val SUCCESS = MethodTemplate.method(typeRef[Unit], "success"). + expression( + invoke(get(self(), typeRef[SuccessfulCloseable], "closeable"), method[SuccessfulCloseable, Unit]("success"))). + build() + val CLOSE = MethodTemplate.method(typeRef[Unit], "close"). + expression( + invoke(get(self(), typeRef[SuccessfulCloseable], "closeable"), method[SuccessfulCloseable, Unit]("close"))). + build() + val EXECUTION_MODE = MethodTemplate.method(typeRef[ExecutionMode], "executionMode"). + returns(get(self(), typeRef[ExecutionMode], "executionMode")). + build() + val EXECUTION_PLAN_DESCRIPTION = MethodTemplate.method(typeRef[InternalPlanDescription], "executionPlanDescription"). + returns(cast( typeRef[InternalPlanDescription], + invoke(get(self(), typeRef[Provider[InternalPlanDescription]], "description"), + method[Provider[InternalPlanDescription], Object]("get")))). + build() + val JAVA_COLUMNS = MethodTemplate.method(typeRef[util.List[String]], "javaColumns"). + returns(get(typeRef[util.List[String]], "COLUMNS")). + build() +} diff --git a/community/cypher/cypher/src/test/java/org/neo4j/cypher/QueryExecutionMonitorTest.scala b/community/cypher/cypher/src/test/java/org/neo4j/cypher/QueryExecutionMonitorTest.scala index e3e62ef032b1f..eb147f8fabaf4 100644 --- a/community/cypher/cypher/src/test/java/org/neo4j/cypher/QueryExecutionMonitorTest.scala +++ b/community/cypher/cypher/src/test/java/org/neo4j/cypher/QueryExecutionMonitorTest.scala @@ -250,9 +250,9 @@ class QueryExecutionMonitorTest extends CypherFunSuite with GraphIcing { verify(monitor, times(1)).endSuccess(context) } - test("triggering monitor in 3.0") { + test("triggering monitor in 3.1") { // given - val context = graph.transactionalContext(query = "CYPHER 3.0 RETURN [1, 2, 3, 4, 5]" -> Map.empty) + val context = graph.transactionalContext(query = "CYPHER 3.1 RETURN [1, 2, 3, 4, 5]" -> Map.empty) // when val result = engine.profile(context.queryText(), context.queryParameters(), context).javaIterator @@ -266,9 +266,9 @@ class QueryExecutionMonitorTest extends CypherFunSuite with GraphIcing { verify(monitor, times(1)).endSuccess(context) } - test("monitor is called when iterator closes in 3.0") { + test("monitor is called when iterator closes in 3.1") { // given - val (query, result) = runQuery("CYPHER 3.0 RETURN 42") + val (query, result) = runQuery("CYPHER 3.1 RETURN 42") // when val iterator = result.javaIterator @@ -279,9 +279,9 @@ class QueryExecutionMonitorTest extends CypherFunSuite with GraphIcing { verify(monitor, times(1)).endSuccess(query) } - test("monitor is called when next on empty iterator in 3.0") { + test("monitor is called when next on empty iterator in 3.1") { // given - val (query, result) = runQuery("CYPHER 3.0 RETURN 42") + val (query, result) = runQuery("CYPHER 3.1 RETURN 42") // when val iterator = result.javaIterator @@ -293,9 +293,9 @@ class QueryExecutionMonitorTest extends CypherFunSuite with GraphIcing { verify(monitor, times(1)).endSuccess(query) } - test("monitor is called directly when return is empty in 3.0") { + test("monitor is called directly when return is empty in 3.1") { // given - val (query, result) = runQuery("CYPHER 3.0 CREATE()") + val (query, result) = runQuery("CYPHER 3.1 CREATE()") // when result.javaIterator diff --git a/community/cypher/cypher/src/test/java/org/neo4j/cypher/internal/CypherStatementWithOptionsTest.scala b/community/cypher/cypher/src/test/java/org/neo4j/cypher/internal/CypherStatementWithOptionsTest.scala index 3c16320b42974..fbc37fdab5fb0 100644 --- a/community/cypher/cypher/src/test/java/org/neo4j/cypher/internal/CypherStatementWithOptionsTest.scala +++ b/community/cypher/cypher/src/test/java/org/neo4j/cypher/internal/CypherStatementWithOptionsTest.scala @@ -33,7 +33,7 @@ class CypherStatementWithOptionsTest extends CypherFunSuite { } test("should not allow multiple versions") { - intercept[InvalidArgumentException](CypherStatementWithOptions("CYPHER 2.3 CYPHER 3.0 RETURN 42")) + intercept[InvalidArgumentException](CypherStatementWithOptions("CYPHER 2.3 CYPHER 3.1 RETURN 42")) } test("should not allow both EXPLAIN and PROFILE") { diff --git a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/CartesianProductNotificationAcceptanceTest.scala b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/CartesianProductNotificationAcceptanceTest.scala index 2ea4218ec12b6..cb7bcb40784eb 100644 --- a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/CartesianProductNotificationAcceptanceTest.scala +++ b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/CartesianProductNotificationAcceptanceTest.scala @@ -30,7 +30,7 @@ import org.neo4j.cypher.internal.compiler.v3_2.tracing.rewriters.RewriterStepSeq import org.neo4j.cypher.internal.frontend.v3_2.InputPosition import org.neo4j.cypher.internal.frontend.v3_2.notification.CartesianProductNotification import org.neo4j.cypher.internal.frontend.v3_2.test_helpers.CypherFunSuite -import org.neo4j.cypher.internal.spi.v3_1.codegen.GeneratedQueryStructure +import org.neo4j.cypher.internal.spi.v3_2.codegen.GeneratedQueryStructure import org.neo4j.logging.NullLog class CartesianProductNotificationAcceptanceTest extends CypherFunSuite with GraphDatabaseTestSupport { @@ -116,8 +116,8 @@ class CartesianProductNotificationAcceptanceTest extends CypherFunSuite with Gra ), Clock.systemUTC(), GeneratedQueryStructure, - new WrappedMonitors3_1(kernelMonitors), - new StringInfoLogger3_1(NullLog.getInstance), + new WrappedMonitors3_2(kernelMonitors), + new StringInfoLogger3_2(NullLog.getInstance), plannerName = Some(IDPPlannerName), runtimeName = Some(CompiledRuntimeName), updateStrategy = None, diff --git a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/CypherCompatibilityTest.scala b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/CypherCompatibilityTest.scala index a02b050a0ef8b..0e39a0a9f991e 100644 --- a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/CypherCompatibilityTest.scala +++ b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/CypherCompatibilityTest.scala @@ -38,22 +38,24 @@ class CypherCompatibilityTest extends ExecutionEngineFunSuite with RunWithConfig execute(s"CYPHER 2.3 $query").columnAs[Long]("count(*)").next() shouldBe 1 execute(s"CYPHER 3.1 planner=rule $query").columnAs[Long]("count(*)").next() shouldBe 1 execute(s"CYPHER 3.1 $query").columnAs[Long]("count(*)").next() shouldBe 1 + execute(s"CYPHER 3.2 planner=rule $query").columnAs[Long]("count(*)").next() shouldBe 1 + execute(s"CYPHER 3.2 $query").columnAs[Long]("count(*)").next() shouldBe 1 } test("should be able to switch between versions") { runWithConfig() { db => db.execute(s"CYPHER 2.3 $QUERY").asScala.toList shouldBe empty - db.execute(s"CYPHER 3.0 $QUERY").asScala.toList shouldBe empty db.execute(s"CYPHER 3.1 $QUERY").asScala.toList shouldBe empty + db.execute(s"CYPHER 3.2 $QUERY").asScala.toList shouldBe empty } } test("should be able to switch between versions2") { runWithConfig() { db => + db.execute(s"CYPHER 3.2 $QUERY").asScala.toList shouldBe empty db.execute(s"CYPHER 3.1 $QUERY").asScala.toList shouldBe empty - db.execute(s"CYPHER 3.0 $QUERY").asScala.toList shouldBe empty db.execute(s"CYPHER 2.3 $QUERY").asScala.toList shouldBe empty } } @@ -77,16 +79,15 @@ class CypherCompatibilityTest extends ExecutionEngineFunSuite with RunWithConfig db => val result = db.execute(QUERY) result.asScala.toList shouldBe empty - result.getExecutionPlanDescription.getArguments.get("version") should equal("CYPHER 3.1") + result.getExecutionPlanDescription.getArguments.get("version") should equal("CYPHER 3.2") } } - //TODO fix this test - ignore("should handle profile in compiled runtime") { + test("should handle profile in compiled runtime") { runWithConfig() { db => - assertProfiled(db, "CYPHER 2.3 runtime=compiled PROFILE MATCH (n) RETURN n") - assertProfiled(db, "CYPHER 3.0 runtime=compiled PROFILE MATCH (n) RETURN n") + assertProfiled(db, "CYPHER 3.1 runtime=compiled PROFILE MATCH (n) RETURN n") + assertProfiled(db, "CYPHER 3.2 runtime=compiled PROFILE MATCH (n) RETURN n") } } @@ -94,8 +95,8 @@ class CypherCompatibilityTest extends ExecutionEngineFunSuite with RunWithConfig runWithConfig() { engine => assertProfiled(engine, "CYPHER 2.3 runtime=interpreted PROFILE MATCH (n) RETURN n") - assertProfiled(engine, "CYPHER 3.0 runtime=interpreted PROFILE MATCH (n) RETURN n") assertProfiled(engine, "CYPHER 3.1 runtime=interpreted PROFILE MATCH (n) RETURN n") + assertProfiled(engine, "CYPHER 3.2 runtime=interpreted PROFILE MATCH (n) RETURN n") } } @@ -103,8 +104,8 @@ class CypherCompatibilityTest extends ExecutionEngineFunSuite with RunWithConfig runWithConfig() { engine => assertExplained(engine, "CYPHER 2.3 EXPLAIN MATCH (n) RETURN n") - assertExplained(engine, "CYPHER 3.0 EXPLAIN MATCH (n) RETURN n") assertExplained(engine, "CYPHER 3.1 EXPLAIN MATCH (n) RETURN n") + assertExplained(engine, "CYPHER 3.2 EXPLAIN MATCH (n) RETURN n") } } diff --git a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/GraphDatabaseTestSupport.scala b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/GraphDatabaseTestSupport.scala index c7b0c33c19c55..0d8b43ef5029c 100644 --- a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/GraphDatabaseTestSupport.scala +++ b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/GraphDatabaseTestSupport.scala @@ -25,9 +25,9 @@ import org.neo4j.cypher.internal.compiler.v3_2.spi.PlanContext import org.neo4j.cypher.internal.compiler.v3_2.{CypherCompilerConfiguration, devNullLogger} import org.neo4j.cypher.internal.frontend.v3_2.test_helpers.{CypherFunSuite, CypherTestSupport} import org.neo4j.cypher.internal.helpers.GraphIcing -import org.neo4j.cypher.internal.spi.TransactionalContextWrapperv3_1 -import org.neo4j.cypher.internal.spi.v3_1.TransactionBoundPlanContext -import org.neo4j.cypher.internal.spi.v3_1.TransactionBoundQueryContext.IndexSearchMonitor +import org.neo4j.cypher.internal.spi.TransactionalContextWrapperv3_2 +import org.neo4j.cypher.internal.spi.v3_2.TransactionBoundPlanContext +import org.neo4j.cypher.internal.spi.v3_2.TransactionBoundQueryContext.IndexSearchMonitor import org.neo4j.cypher.javacompat.internal.GraphDatabaseCypherService import org.neo4j.graphdb._ import org.neo4j.graphdb.config.Setting @@ -250,7 +250,7 @@ trait GraphDatabaseTestSupport extends CypherTestSupport with GraphIcing { def kernelAPI = graph.getDependencyResolver.resolveDependency(classOf[KernelAPI]) def planContext: PlanContext = { - val tc = mock[TransactionalContextWrapperv3_1] + val tc = mock[TransactionalContextWrapperv3_2] when(tc.statement).thenReturn(statement) when(tc.readOperations).thenReturn(statement.readOperations()) when(tc.graph).thenReturn(graph) diff --git a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/NewPlannerTestSupport.scala b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/NewPlannerTestSupport.scala index 103107386256c..85bac1fb79425 100644 --- a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/NewPlannerTestSupport.scala +++ b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/NewPlannerTestSupport.scala @@ -21,20 +21,19 @@ package org.neo4j.cypher import org.neo4j.cypher.NewPlannerMonitor.{NewPlannerMonitorCall, NewQuerySeen, UnableToHandleQuery} import org.neo4j.cypher.NewRuntimeMonitor.{NewPlanSeen, NewRuntimeMonitorCall, UnableToCompileQuery} -import org.neo4j.cypher.internal.{ExecutionResult, RewindableExecutionResult} -import org.neo4j.cypher.internal.compatibility.{ClosingExecutionResult, ExecutionResultWrapperFor2_3, ExecutionResultWrapperFor3_1} +import org.neo4j.cypher.internal.compatibility.{ClosingExecutionResult, ExecutionResultWrapperFor2_3, ExecutionResultWrapperFor3_1, ExecutionResultWrapperFor3_2} import org.neo4j.cypher.internal.compiler.v3_2.executionplan.{InternalExecutionResult, NewLogicalPlanSuccessRateMonitor, NewRuntimeSuccessRateMonitor} import org.neo4j.cypher.internal.compiler.v3_2.planner.logical.plans.LogicalPlan import org.neo4j.cypher.internal.compiler.v3_2.planner.{CantCompileQueryException, CantHandleQueryException} import org.neo4j.cypher.internal.frontend.v3_2.ast.Statement import org.neo4j.cypher.internal.frontend.v3_2.helpers.Eagerly import org.neo4j.cypher.internal.frontend.v3_2.test_helpers.CypherTestSupport +import org.neo4j.cypher.internal.{ExecutionResult, RewindableExecutionResult} import org.neo4j.graphdb.config.Setting import org.neo4j.graphdb.factory.GraphDatabaseSettings import org.neo4j.helpers.Exceptions import org.scalatest.matchers.{MatchResult, Matcher} -import scala.annotation.tailrec import scala.util.{Failure, Success, Try} object NewPlannerMonitor { @@ -101,7 +100,7 @@ trait NewPlannerTestSupport extends CypherTestSupport { self: ExecutionEngineFunSuite => override def databaseConfig(): Map[Setting[_], String] = - Map(GraphDatabaseSettings.cypher_parser_version -> CypherVersion.v3_1.name, + Map(GraphDatabaseSettings.cypher_parser_version -> CypherVersion.v3_2.name, //TODO: This should not be specified here GraphDatabaseSettings.query_non_indexed_label_warning_threshold -> "10") val newPlannerMonitor = new NewPlannerMonitor @@ -286,6 +285,7 @@ trait NewPlannerTestSupport extends CypherTestSupport { private def rewindableResult(result: ExecutionResult): InternalExecutionResult = { result match { case e: ClosingExecutionResult => e.inner match { + case _: ExecutionResultWrapperFor3_2 => RewindableExecutionResult(e) case _: ExecutionResultWrapperFor3_1 => RewindableExecutionResult(e) case _: ExecutionResultWrapperFor2_3 => RewindableExecutionResult(e) } diff --git a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/ProfilerAcceptanceTest.scala b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/ProfilerAcceptanceTest.scala index d604ed318d752..01f17d3ab530d 100644 --- a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/ProfilerAcceptanceTest.scala +++ b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/ProfilerAcceptanceTest.scala @@ -137,8 +137,8 @@ class ProfilerAcceptanceTest extends ExecutionEngineFunSuite with CreateTempFile result.getExecutionPlanDescription.toString should include("DB Hits") } - test("PROFILE for Cypher 3,0") { - val result = graph.execute("cypher 3.0 profile match (n) where (n)-[:FOO]->() return *") + test("PROFILE for Cypher 3.1") { + val result = graph.execute("cypher 3.1 profile match (n) where (n)-[:FOO]->() return *") assert(result.getQueryExecutionType.requestedExecutionPlanDescription, "result not marked with planDescriptionRequested") result.getExecutionPlanDescription.toString should include("DB Hits") diff --git a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/QueryCachingTest.scala b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/QueryCachingTest.scala index 945dcc33a1f7f..b28649100282b 100644 --- a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/QueryCachingTest.scala +++ b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/QueryCachingTest.scala @@ -67,9 +67,9 @@ class QueryCachingTest extends CypherFunSuite with GraphDatabaseTestSupport with val actual = cacheListener.trace val expected = List( s"cacheFlushDetected", - s"cacheMiss: CYPHER 3.1 $query", - s"cacheHit: CYPHER 3.1 $query", - s"cacheHit: CYPHER 3.1 $query") + s"cacheMiss: CYPHER 3.2 $query", + s"cacheHit: CYPHER 3.2 $query", + s"cacheHit: CYPHER 3.2 $query") actual should equal(expected) } diff --git a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/QueryStatisticsTestSupport.scala b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/QueryStatisticsTestSupport.scala index c2ad2eb4dad09..58a2633a0f8f6 100644 --- a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/QueryStatisticsTestSupport.scala +++ b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/QueryStatisticsTestSupport.scala @@ -20,7 +20,7 @@ package org.neo4j.cypher import org.neo4j.cypher.internal.QueryStatistics -import org.neo4j.cypher.internal.compatibility.ExecutionResultWrapperFor3_1 +import org.neo4j.cypher.internal.compatibility.{ExecutionResultWrapperFor3_1, ExecutionResultWrapperFor3_2} import org.neo4j.cypher.internal.compiler.v3_2.executionplan.InternalExecutionResult import org.neo4j.cypher.internal.compiler.v3_2.{CompiledRuntimeName, CostBasedPlannerName} import org.neo4j.kernel.api.ExecutingQuery @@ -44,7 +44,7 @@ trait QueryStatisticsTestSupport extends MockitoSugar { override def endFailure(query: ExecutingQuery, throwable: Throwable){} } - val r = new ExecutionResultWrapperFor3_1(actual, CostBasedPlannerName.default, CompiledRuntimeName) + val r = new ExecutionResultWrapperFor3_2(actual, CostBasedPlannerName.default, CompiledRuntimeName) apply(r.queryStatistics()) } } diff --git a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/RootPlanAcceptanceTest.scala b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/RootPlanAcceptanceTest.scala index 3ef19cc7161b9..27d4c9632443f 100644 --- a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/RootPlanAcceptanceTest.scala +++ b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/RootPlanAcceptanceTest.scala @@ -20,40 +20,39 @@ package org.neo4j.cypher import org.neo4j.cypher.internal.compiler.v3_2._ -import org.neo4j.kernel.impl.query.TransactionalContext class RootPlanAcceptanceTest extends ExecutionEngineFunSuite { - test("cost should be default planner in 3.1") { + test("cost should be default planner in 3.2") { given("match (n) return n") - .withCypherVersion(CypherVersion.v3_1) + .withCypherVersion(CypherVersion.v3_2) .shouldHavePlanner(CostBasedPlannerName.default) } - test("interpreted should be default runtime in 3.1") { + test("interpreted should be default runtime in 3.2") { given("match (n) return n") - .withCypherVersion(CypherVersion.v3_1) + .withCypherVersion(CypherVersion.v3_2) .shouldHaveRuntime(InterpretedRuntimeName) } - test("should use cost for varlength in 3.1") { + test("should use cost for varlength in 3.2") { given("match (a)-[r:T1*]->(b) return a,r,b") - .withCypherVersion(CypherVersion.v3_1) - .shouldHaveCypherVersion(CypherVersion.v3_1) + .withCypherVersion(CypherVersion.v3_2) + .shouldHaveCypherVersion(CypherVersion.v3_2) .shouldHavePlanner(CostBasedPlannerName.default) } - test("should use cost for cycles in 3.1") { + test("should use cost for cycles in 3.2") { given("match (a)-[r]->(a) return a") - .withCypherVersion(CypherVersion.v3_1) - .shouldHaveCypherVersion(CypherVersion.v3_1) + .withCypherVersion(CypherVersion.v3_2) + .shouldHaveCypherVersion(CypherVersion.v3_2) .shouldHavePlanner(CostBasedPlannerName.default) } - test("should handle updates in 3.1") { + test("should handle updates in 3.2") { given("create() return 1") - .withCypherVersion(CypherVersion.v3_1) - .shouldHaveCypherVersion(CypherVersion.v3_1) + .withCypherVersion(CypherVersion.v3_2) + .shouldHaveCypherVersion(CypherVersion.v3_2) .shouldHavePlanner(CostBasedPlannerName.default) } @@ -62,9 +61,9 @@ class RootPlanAcceptanceTest extends ExecutionEngineFunSuite { """MATCH p=(n:Person {first_name: 'Shawna'})-[:FRIEND_OF]-(m:Person) |RETURN p UNION MATCH p=(n:Person {first_name: 'Shawna'})-[:FRIEND_OF]-()-[:FRIEND_OF]-(m:Person) RETURN p""" .stripMargin) - .withCypherVersion(CypherVersion.v3_1) + .withCypherVersion(CypherVersion.v3_2) .withPlanner(RulePlannerName) - .shouldHaveCypherVersion(CypherVersion.v3_1) + .shouldHaveCypherVersion(CypherVersion.v3_2) .shouldHavePlanner(RulePlannerName) } @@ -75,8 +74,8 @@ class RootPlanAcceptanceTest extends ExecutionEngineFunSuite { |RETURN coc, COUNT(*) AS times |ORDER BY times DESC |LIMIT 10""".stripMargin) - .withCypherVersion(CypherVersion.v3_1) - .shouldHaveCypherVersion(CypherVersion.v3_1) + .withCypherVersion(CypherVersion.v3_2) + .shouldHaveCypherVersion(CypherVersion.v3_2) .shouldHavePlanner(CostBasedPlannerName.default) } @@ -85,31 +84,31 @@ class RootPlanAcceptanceTest extends ExecutionEngineFunSuite { """MATCH (s:Location {name:'DeliverySegment-257227'}), (e:Location {name:'DeliverySegment-476821'}) |MATCH (s)<-[:DELIVERY_ROUTE]-(db1) MATCH (db2)-[:DELIVERY_ROUTE]->(e) |MATCH (db1)<-[:CONNECTED_TO]-()-[:CONNECTED_TO]-(db2) RETURN s""".stripMargin) - .withCypherVersion(CypherVersion.v3_1) - .shouldHaveCypherVersion(CypherVersion.v3_1) + .withCypherVersion(CypherVersion.v3_2) + .shouldHaveCypherVersion(CypherVersion.v3_2) .shouldHavePlanner(CostBasedPlannerName.default) } test("query that does not go through the compiled runtime") { given("MATCH (n) RETURN n, count(*)") - .withCypherVersion(CypherVersion.v3_1) - .shouldHaveCypherVersion(CypherVersion.v3_1) + .withCypherVersion(CypherVersion.v3_2) + .shouldHaveCypherVersion(CypherVersion.v3_2) .shouldHaveRuntime(InterpretedRuntimeName) } test("query that lacks support from the compiled runtime") { given("CREATE ()") - .withCypherVersion(CypherVersion.v3_1) + .withCypherVersion(CypherVersion.v3_2) .withRuntime(CompiledRuntimeName) - .shouldHaveCypherVersion(CypherVersion.v3_1) + .shouldHaveCypherVersion(CypherVersion.v3_2) .shouldHaveRuntime(InterpretedRuntimeName) } test("query that should go through the compiled runtime") { given("MATCH (a)-->(b) RETURN a") - .withCypherVersion(CypherVersion.v3_1) + .withCypherVersion(CypherVersion.v3_2) .withRuntime(CompiledRuntimeName) - .shouldHaveCypherVersion(CypherVersion.v3_1) + .shouldHaveCypherVersion(CypherVersion.v3_2) .shouldHaveRuntime(CompiledRuntimeName) .shouldHavePlanner(CostBasedPlannerName.default) } @@ -170,7 +169,7 @@ class RootPlanAcceptanceTest extends ExecutionEngineFunSuite { given("match (n) return n") .withPlanner(planner) .withRuntime(runtime) - .shouldHaveCypherVersion(CypherVersion.v3_1) + .shouldHaveCypherVersion(CypherVersion.v3_2) .shouldHavePlanner(planner) .shouldHaveRuntime(runtime) } diff --git a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/UniqueIndexUsageAcceptanceTest.scala b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/UniqueIndexUsageAcceptanceTest.scala index 0b183f92f986f..da72810538637 100644 --- a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/UniqueIndexUsageAcceptanceTest.scala +++ b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/UniqueIndexUsageAcceptanceTest.scala @@ -19,7 +19,7 @@ */ package org.neo4j.cypher -import org.neo4j.cypher.internal.spi.v3_0.TransactionBoundQueryContext.IndexSearchMonitor +import org.neo4j.cypher.internal.spi.v3_2.TransactionBoundQueryContext.IndexSearchMonitor import org.neo4j.kernel.api.index.IndexDescriptor class UniqueIndexUsageAcceptanceTest extends ExecutionEngineFunSuite with NewPlannerTestSupport { diff --git a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/RewindableExecutionResult.scala b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/RewindableExecutionResult.scala index c0cd364c26ccf..43225ee894fba 100644 --- a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/RewindableExecutionResult.scala +++ b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/RewindableExecutionResult.scala @@ -24,13 +24,14 @@ import java.util import org.neo4j.cypher.InternalException import org.neo4j.cypher.internal.compatibility._ -import org.neo4j.cypher.internal.compiler.v2_3 +import org.neo4j.cypher.internal.compiler.{v2_3, v3_1} import org.neo4j.cypher.internal.compiler.v3_2._ import org.neo4j.cypher.internal.compiler.v3_2.executionplan.{InternalExecutionResult, READ_WRITE, _} import org.neo4j.cypher.internal.compiler.v3_2.planDescription.InternalPlanDescription.Arguments import org.neo4j.cypher.internal.compiler.v3_2.planDescription._ import org.neo4j.cypher.internal.compiler.v3_2.spi.InternalResultVisitor import org.neo4j.cypher.internal.frontend.v2_3.{notification => notification_2_3} +import org.neo4j.cypher.internal.frontend.v3_1.{notification => notification_3_1} import org.neo4j.cypher.internal.frontend.v3_2.{InputPosition, notification} import org.neo4j.graphdb.{QueryExecutionType, ResourceIterator} @@ -72,10 +73,29 @@ object RewindableExecutionResult { InternalExecutionResultCompatibilityWrapperFor2_3(result) } - // TODO: Should this not also include 3.0 results? + private def compatibility(inner: v3_1.executionplan.InternalExecutionResult, planner: v3_1.PlannerName, runtime: v3_1.RuntimeName): InternalExecutionResult = { + val result: v3_1.executionplan.InternalExecutionResult = inner match { + case other: v3_1.PipeExecutionResult => + exceptionHandlerFor2_3.runSafely { + new v3_1.PipeExecutionResult(other.result.toEager, other.columns, other.state, other.executionPlanBuilder, + other.executionMode, v3_1.executionplan.READ_WRITE) { + override def executionPlanDescription(): v3_1.planDescription.InternalPlanDescription = super.executionPlanDescription() + .addArgument(v3_1.planDescription.InternalPlanDescription.Arguments.Planner(planner.name)) + .addArgument(v3_1.planDescription.InternalPlanDescription.Arguments.Runtime(runtime.name)) + } + } + case _ => + inner + } + InternalExecutionResultCompatibilityWrapperFor3_1(result) + } + + def apply(in: ExecutionResult): InternalExecutionResult = in match { + case ExecutionResultWrapperFor3_2(inner, planner, runtime) => + exceptionHandlerFor3_2.runSafely(current(inner, planner, runtime)) case ExecutionResultWrapperFor3_1(inner, planner, runtime) => - exceptionHandlerFor3_1.runSafely(current(inner, planner, runtime)) + exceptionHandlerFor3_1.runSafely(compatibility(inner, planner, runtime)) case ExecutionResultWrapperFor2_3(inner, planner, runtime) => exceptionHandlerFor2_3.runSafely(compatibility(inner, planner, runtime)) case _ => @@ -193,4 +213,112 @@ object RewindableExecutionResult { override def hasNext: Boolean = inner.hasNext } + private case class InternalExecutionResultCompatibilityWrapperFor3_1(inner: v3_1.executionplan.InternalExecutionResult) extends InternalExecutionResult { + override def javaIterator: ResourceIterator[util.Map[String, Any]] = inner.javaIterator + + override def executionType: InternalQueryType = inner.executionType match { + case v3_1.executionplan.READ_ONLY => READ_ONLY + case v3_1.executionplan.READ_WRITE => READ_WRITE + case v3_1.executionplan.WRITE => WRITE + case v3_1.executionplan.SCHEMA_WRITE => SCHEMA_WRITE + } + + override def columnAs[T](column: String): Iterator[T] = inner.columnAs(column) + + override def columns: List[String] = inner.columns + + override def javaColumns: util.List[String] = inner.javaColumns + + override def queryStatistics(): InternalQueryStatistics = { + val stats = inner.queryStatistics() + new InternalQueryStatistics(stats.nodesCreated, stats.relationshipsCreated, stats.propertiesSet, + stats.nodesDeleted, stats.relationshipsDeleted, stats.labelsAdded, stats.labelsRemoved, + stats.indexesAdded, stats.indexesRemoved, stats.uniqueConstraintsAdded, stats.uniqueConstraintsRemoved, + stats.existenceConstraintsAdded, stats.existenceConstraintsRemoved) + } + + override def executionMode: ExecutionMode = NormalMode + + override def dumpToString(writer: PrintWriter): Unit = inner.dumpToString(writer) + + override def dumpToString(): String = inner.dumpToString() + + @throws(classOf[Exception]) + override def accept[EX <: Exception](visitor: InternalResultVisitor[EX]): Unit = ??? + + override def javaColumnAs[T](column: String): ResourceIterator[T] = inner.javaColumnAs(column) + + override def executionPlanDescription(): InternalPlanDescription = lift(inner.executionPlanDescription()) + + private def lift(planDescription: v3_1.planDescription.InternalPlanDescription): InternalPlanDescription = { + val name: String = planDescription.name + val children: Children = planDescription.children match { + case v3_1.planDescription.NoChildren => NoChildren + case v3_1.planDescription.SingleChild(child) => SingleChild(lift(child)) + case v3_1.planDescription.TwoChildren(left, right) => TwoChildren(lift(left), lift(right)) + } + + val arguments: Seq[Argument] = planDescription.arguments.map { + case v3_1.planDescription.InternalPlanDescription.Arguments.Time(value) => Arguments.Time(value) + case v3_1.planDescription.InternalPlanDescription.Arguments.Rows(value) => Arguments.Rows(value) + case v3_1.planDescription.InternalPlanDescription.Arguments.DbHits(value) => Arguments.DbHits(value) + case v3_1.planDescription.InternalPlanDescription.Arguments.ColumnsLeft(value) => Arguments.ColumnsLeft(value) + case v3_1.planDescription.InternalPlanDescription.Arguments.Expression(_) => Arguments.Expression(null) + case v3_1.planDescription.InternalPlanDescription.Arguments.LegacyExpression(_) => Arguments.LegacyExpression(null) + case v3_1.planDescription.InternalPlanDescription.Arguments.UpdateActionName(value) => Arguments.UpdateActionName(value) + case v3_1.planDescription.InternalPlanDescription.Arguments.MergePattern(startPoint) => Arguments.MergePattern(startPoint) + case v3_1.planDescription.InternalPlanDescription.Arguments.LegacyIndex(value) => Arguments.LegacyIndex(value) + case v3_1.planDescription.InternalPlanDescription.Arguments.Index(label, propertyKey) => Arguments.Index(label, propertyKey) + case v3_1.planDescription.InternalPlanDescription.Arguments.PrefixIndex(label, propertyKey, _) => Arguments.PrefixIndex(label, propertyKey, null) + case v3_1.planDescription.InternalPlanDescription.Arguments.InequalityIndex(label, propertyKey, bounds) => Arguments.InequalityIndex(label, propertyKey, bounds) + case v3_1.planDescription.InternalPlanDescription.Arguments.LabelName(label) => Arguments.LabelName(label) + case v3_1.planDescription.InternalPlanDescription.Arguments.KeyNames(keys) => Arguments.KeyNames(keys) + case v3_1.planDescription.InternalPlanDescription.Arguments.KeyExpressions(_) => Arguments.KeyExpressions(null) + case v3_1.planDescription.InternalPlanDescription.Arguments.EntityByIdRhs(_) => Arguments.EntityByIdRhs(null) + case v3_1.planDescription.InternalPlanDescription.Arguments.EstimatedRows(value) => Arguments.EstimatedRows(value) + case v3_1.planDescription.InternalPlanDescription.Arguments.Version(value) => Arguments.Version(value) + case v3_1.planDescription.InternalPlanDescription.Arguments.Planner(value) => Arguments.Planner(value) + case v3_1.planDescription.InternalPlanDescription.Arguments.PlannerImpl(value) => Arguments.PlannerImpl(value) + case v3_1.planDescription.InternalPlanDescription.Arguments.Runtime(value) => Arguments.Runtime(value) + case v3_1.planDescription.InternalPlanDescription.Arguments.RuntimeImpl(value) => Arguments.RuntimeImpl(value) + case v3_1.planDescription.InternalPlanDescription.Arguments.ExpandExpression(from, relName, relTypes, to, _, varLength) => + Arguments.ExpandExpression(from, relName, relTypes, to, null, varLength) + case v3_1.planDescription.InternalPlanDescription.Arguments.SourceCode(className, sourceCode) => + Arguments.SourceCode(className, sourceCode) + } + new PlanDescriptionImpl( new Id, name, children, arguments, planDescription.variables) + } + + + override def close(): Unit = inner.close() + + override def notifications: Iterable[notification.InternalNotification] = inner.notifications.map { + case notification_3_1.CartesianProductNotification(position, isolatedVariables) => notification.CartesianProductNotification(lift(position), isolatedVariables) + case notification_3_1.LengthOnNonPathNotification(position) => notification.LengthOnNonPathNotification(InputPosition.apply(position.offset, position.line, position.column)) + case notification_3_1.PlannerUnsupportedNotification => notification.PlannerUnsupportedNotification + case notification_3_1.RuntimeUnsupportedNotification => notification.RuntimeUnsupportedNotification + case notification_3_1.IndexHintUnfulfillableNotification (label, propertyKey) => notification.IndexHintUnfulfillableNotification(label, propertyKey) + case notification_3_1.JoinHintUnfulfillableNotification(identified) => notification.JoinHintUnfulfillableNotification(identified) + case notification_3_1.JoinHintUnsupportedNotification(identified) => notification.JoinHintUnsupportedNotification(identified) + case notification_3_1.IndexLookupUnfulfillableNotification(labels) => notification.IndexLookupUnfulfillableNotification(labels) + case notification_3_1.EagerLoadCsvNotification => notification.EagerLoadCsvNotification + case notification_3_1.LargeLabelWithLoadCsvNotification => notification.LargeLabelWithLoadCsvNotification + case notification_3_1.MissingLabelNotification(position, label) => notification.MissingLabelNotification(lift(position), label) + case notification_3_1.MissingRelTypeNotification(position, relType) => notification.MissingRelTypeNotification(lift(position), relType) + case notification_3_1.MissingPropertyNameNotification(position, name) => notification.MissingPropertyNameNotification(lift(position), name) + case notification_3_1.UnboundedShortestPathNotification(position) => notification.UnboundedShortestPathNotification(lift(position)) + case notification_3_1.DeprecatedProcedureNotification(position, oldName, newName) => notification.DeprecatedProcedureNotification(lift(position), oldName, newName) + } + + private def lift(position: frontend.v3_1.InputPosition): InputPosition = { + InputPosition.apply(position.offset, position.line, position.column) + } + + override def planDescriptionRequested: Boolean = inner.planDescriptionRequested + + override def next(): Map[String, Any] = inner.next() + + override def hasNext: Boolean = inner.hasNext + } + } diff --git a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/CypherCompilerPerformanceTest.scala b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/CypherCompilerPerformanceTest.scala index b94620846ffd8..952a13de815f1 100644 --- a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/CypherCompilerPerformanceTest.scala +++ b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/CypherCompilerPerformanceTest.scala @@ -21,11 +21,11 @@ package org.neo4j.cypher.internal.compiler import org.neo4j.cypher.GraphDatabaseFunSuite import org.neo4j.cypher.internal.CypherCompiler.{CLOCK, DEFAULT_QUERY_PLAN_TTL, DEFAULT_STATISTICS_DIVERGENCE_THRESHOLD} -import org.neo4j.cypher.internal.compatibility.WrappedMonitors3_1 +import org.neo4j.cypher.internal.compatibility.WrappedMonitors3_2 import org.neo4j.cypher.internal.compiler.v3_2.helpers.IdentityTypeConverter import org.neo4j.cypher.internal.compiler.v3_2.tracing.rewriters.RewriterStepSequencer import org.neo4j.cypher.internal.compiler.v3_2.{CypherCompilerFactory, InfoLogger, _} -import org.neo4j.cypher.internal.spi.v3_1.codegen.GeneratedQueryStructure +import org.neo4j.cypher.internal.spi.v3_2.codegen.GeneratedQueryStructure import scala.concurrent.duration._ @@ -197,7 +197,7 @@ class CypherCompilerPerformanceTest extends GraphDatabaseFunSuite { ), clock = CLOCK, structure = GeneratedQueryStructure, - monitors = new WrappedMonitors3_1(kernelMonitors), + monitors = new WrappedMonitors3_2(kernelMonitors), logger = DEV_NULL, rewriterSequencer = RewriterStepSequencer.newPlain, plannerName = Some(IDPPlannerName), diff --git a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/v3_2/CompilerComparisonTest.scala b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/v3_2/CompilerComparisonTest.scala index a5755a4f5d139..6165e2e0c7008 100644 --- a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/v3_2/CompilerComparisonTest.scala +++ b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/v3_2/CompilerComparisonTest.scala @@ -24,7 +24,7 @@ import java.text.NumberFormat import java.time.Clock import java.util.{Collections, Date, Locale} -import org.neo4j.cypher.internal.compatibility.WrappedMonitors3_1 +import org.neo4j.cypher.internal.compatibility.WrappedMonitors3_2 import org.neo4j.cypher.internal.compiler.v3_2.executionplan._ import org.neo4j.cypher.internal.compiler.v3_2.helpers.IdentityTypeConverter import org.neo4j.cypher.internal.compiler.v3_2.planDescription.InternalPlanDescription @@ -34,9 +34,9 @@ import org.neo4j.cypher.internal.compiler.v3_2.planner.logical.plans.rewriter.Lo import org.neo4j.cypher.internal.compiler.v3_2.tracing.rewriters.RewriterStepSequencer import org.neo4j.cypher.internal.frontend.v3_2.ast.Statement import org.neo4j.cypher.internal.frontend.v3_2.parser.CypherParser -import org.neo4j.cypher.internal.spi.TransactionalContextWrapperv3_1 -import org.neo4j.cypher.internal.spi.v3_1.codegen.GeneratedQueryStructure -import org.neo4j.cypher.internal.spi.v3_1.{TransactionBoundPlanContext, TransactionBoundQueryContext} +import org.neo4j.cypher.internal.spi.TransactionalContextWrapperv3_2 +import org.neo4j.cypher.internal.spi.v3_2.codegen.GeneratedQueryStructure +import org.neo4j.cypher.internal.spi.v3_2.{TransactionBoundPlanContext, TransactionBoundQueryContext} import org.neo4j.cypher.javacompat.internal.GraphDatabaseCypherService import org.neo4j.cypher.{ExecutionEngineFunSuite, NewPlannerTestSupport, QueryStatisticsTestSupport} import org.neo4j.graphdb.factory.GraphDatabaseFactory @@ -294,7 +294,7 @@ class CompilerComparisonTest extends ExecutionEngineFunSuite with QueryStatistic private def ronjaCompiler(plannerName: CostBasedPlannerName, metricsFactoryInput: MetricsFactory = SimpleMetricsFactory)(graph: GraphDatabaseQueryService): CypherCompiler = { val kernelMonitors = new KernelMonitors() - val monitors = WrappedMonitors3_1(kernelMonitors) + val monitors = WrappedMonitors3_2(kernelMonitors) val parser = new CypherParser val checker = new SemanticChecker val rewriter = new ASTRewriter(rewriterSequencer) @@ -329,7 +329,7 @@ class CompilerComparisonTest extends ExecutionEngineFunSuite with QueryStatistic private def legacyCompiler(graph: GraphDatabaseQueryService): CypherCompiler = { val kernelMonitors = new KernelMonitors() - val monitors = WrappedMonitors3_1(kernelMonitors) + val monitors = WrappedMonitors3_2(kernelMonitors) val parser = new CypherParser val checker = new SemanticChecker val rewriter = new ASTRewriter(rewriterSequencer) @@ -550,13 +550,13 @@ class CompilerComparisonTest extends ExecutionEngineFunSuite with QueryStatistic val (executionPlan: ExecutionPlan, extractedParams: Map[String, Any]) = db.withTx { tx => val transactionalContext = contextFactory.newContext(querySource, tx, query, Collections.emptyMap()) - val planContext = new TransactionBoundPlanContext(TransactionalContextWrapperv3_1(transactionalContext), devNullLogger) + val planContext = new TransactionBoundPlanContext(TransactionalContextWrapperv3_2(transactionalContext), devNullLogger) compiler.planQuery(query, planContext, devNullLogger) } db.withTx { tx => val transactionalContext = contextFactory.newContext(querySource, tx, query, Collections.emptyMap()) - val tcWrapper = TransactionalContextWrapperv3_1(transactionalContext) + val tcWrapper = TransactionalContextWrapperv3_2(transactionalContext) val queryContext = new TransactionBoundQueryContext(tcWrapper)(indexSearchMonitor) val result = executionPlan.run(queryContext, ProfileMode, extractedParams) (result.toList, result) diff --git a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/v3_2/CypherCompilerAstCacheAcceptanceTest.scala b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/v3_2/CypherCompilerAstCacheAcceptanceTest.scala index 3d776cefdfcdd..0505942c270bd 100644 --- a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/v3_2/CypherCompilerAstCacheAcceptanceTest.scala +++ b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/v3_2/CypherCompilerAstCacheAcceptanceTest.scala @@ -22,13 +22,13 @@ package org.neo4j.cypher.internal.compiler.v3_2 import java.time.{Clock, Instant, ZoneOffset} import org.neo4j.cypher.GraphDatabaseTestSupport -import org.neo4j.cypher.internal.compatibility.{StringInfoLogger3_1, WrappedMonitors3_1} +import org.neo4j.cypher.internal.compatibility.{StringInfoLogger3_2, WrappedMonitors3_2} import org.neo4j.cypher.internal.compiler.v3_2.executionplan.ExecutionPlan import org.neo4j.cypher.internal.compiler.v3_2.helpers.IdentityTypeConverter import org.neo4j.cypher.internal.compiler.v3_2.tracing.rewriters.RewriterStepSequencer import org.neo4j.cypher.internal.frontend.v3_2.ast.Statement import org.neo4j.cypher.internal.frontend.v3_2.test_helpers.CypherFunSuite -import org.neo4j.cypher.internal.spi.v3_1.codegen.GeneratedQueryStructure +import org.neo4j.cypher.internal.spi.v3_2.codegen.GeneratedQueryStructure import org.neo4j.graphdb.config.Setting import org.neo4j.graphdb.factory.GraphDatabaseSettings import org.neo4j.logging.AssertableLogProvider.inLog @@ -53,8 +53,8 @@ class CypherCompilerAstCacheAcceptanceTest extends CypherFunSuite with GraphData nonIndexedLabelWarningThreshold = 10000L ), clock, GeneratedQueryStructure, - new WrappedMonitors3_1(kernelMonitors), - new StringInfoLogger3_1(log), + new WrappedMonitors3_2(kernelMonitors), + new StringInfoLogger3_2(log), plannerName = Some(IDPPlannerName), runtimeName = Some(CompiledRuntimeName), updateStrategy = None, diff --git a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/v3_2/QueryStateHelper.scala b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/v3_2/QueryStateHelper.scala index 77caa9f56d242..d432514ab45e3 100644 --- a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/v3_2/QueryStateHelper.scala +++ b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/v3_2/QueryStateHelper.scala @@ -23,9 +23,9 @@ import java.util.Collections import org.neo4j.cypher.internal.compiler.v3_2.pipes.{ExternalCSVResource, NullPipeDecorator, PipeDecorator, QueryState} import org.neo4j.cypher.internal.compiler.v3_2.spi.{QueryContext, UpdateCountingQueryContext} -import org.neo4j.cypher.internal.spi.TransactionalContextWrapperv3_1 -import org.neo4j.cypher.internal.spi.v3_1.TransactionBoundQueryContext -import org.neo4j.cypher.internal.spi.v3_1.TransactionBoundQueryContext.IndexSearchMonitor +import org.neo4j.cypher.internal.spi.TransactionalContextWrapperv3_2 +import org.neo4j.cypher.internal.spi.v3_2.TransactionBoundQueryContext +import org.neo4j.cypher.internal.spi.v3_2.TransactionBoundQueryContext.IndexSearchMonitor import org.neo4j.kernel.GraphDatabaseQueryService import org.neo4j.kernel.impl.coreapi.{InternalTransaction, PropertyContainerLocker} import org.neo4j.kernel.impl.query.{Neo4jTransactionalContextFactory, QuerySource} @@ -45,7 +45,7 @@ object QueryStateHelper { def queryStateFrom(db: GraphDatabaseQueryService, tx: InternalTransaction, params: Map[String, Any] = Map.empty): QueryState = { val searchMonitor = new KernelMonitors().newMonitor(classOf[IndexSearchMonitor]) val contextFactory = Neo4jTransactionalContextFactory.create(db, locker) - val transactionalContext = TransactionalContextWrapperv3_1(contextFactory.newContext(QuerySource.UNKNOWN, tx, "X", Collections.emptyMap())) + val transactionalContext = TransactionalContextWrapperv3_2(contextFactory.newContext(QuerySource.UNKNOWN, tx, "X", Collections.emptyMap())) val queryContext = new TransactionBoundQueryContext(transactionalContext)(searchMonitor) newWith(db = db, query = queryContext, params = params) } diff --git a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/v3_2/RuleExecutablePlanBuilderTest.scala b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/v3_2/RuleExecutablePlanBuilderTest.scala index 772135d0500f7..ed749b3f493ae 100644 --- a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/v3_2/RuleExecutablePlanBuilderTest.scala +++ b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/v3_2/RuleExecutablePlanBuilderTest.scala @@ -26,7 +26,7 @@ import java.util.concurrent._ import org.junit.Assert._ import org.mockito.Mockito._ import org.neo4j.cypher.GraphDatabaseTestSupport -import org.neo4j.cypher.internal.compatibility.WrappedMonitors3_1 +import org.neo4j.cypher.internal.compatibility.WrappedMonitors3_2 import org.neo4j.cypher.internal.compiler.v3_2.commands.expressions.{Literal, Variable} import org.neo4j.cypher.internal.compiler.v3_2.commands.predicates.HasLabel import org.neo4j.cypher.internal.compiler.v3_2.commands.values.TokenType.{Label, PropertyKey} @@ -45,12 +45,12 @@ import org.neo4j.cypher.internal.compiler.v3_2.tracing.rewriters.RewriterStepSeq import org.neo4j.cypher.internal.frontend.v3_2.ast.Statement import org.neo4j.cypher.internal.frontend.v3_2.test_helpers.CypherFunSuite import org.neo4j.cypher.internal.frontend.v3_2.{InternalException, Rewriter, Scope, SemanticTable} -import org.neo4j.cypher.internal.spi.TransactionalContextWrapperv3_1 -import org.neo4j.cypher.internal.spi.v3_1.TransactionBoundQueryContext -import org.neo4j.cypher.internal.spi.v3_1.codegen.GeneratedQueryStructure +import org.neo4j.cypher.internal.spi.TransactionalContextWrapperv3_2 +import org.neo4j.cypher.internal.spi.v3_2.TransactionBoundQueryContext +import org.neo4j.cypher.internal.spi.v3_2.codegen.GeneratedQueryStructure import org.neo4j.graphdb.Label.label import org.neo4j.kernel.api.KernelTransaction -import org.neo4j.kernel.api.security.{AnonymousContext, SecurityContext} +import org.neo4j.kernel.api.security.AnonymousContext import org.neo4j.kernel.impl.coreapi.PropertyContainerLocker import org.neo4j.kernel.impl.query.{Neo4jTransactionalContextFactory, QuerySource} import org.scalatest.mock.MockitoSugar @@ -96,7 +96,7 @@ class RuleExecutablePlanBuilderTest when(planContext.notificationLogger()).thenReturn(devNullLogger) val exception = intercept[ExecutionException](timeoutAfter(5) { - val pipeBuilder = new LegacyExecutablePlanBuilderWithCustomPlanBuilders(Seq(new BadBuilder), WrappedMonitors3_1(kernelMonitors), config) + val pipeBuilder = new LegacyExecutablePlanBuilderWithCustomPlanBuilders(Seq(new BadBuilder), WrappedMonitors3_2(kernelMonitors), config) val query = new FakePreparedSemanticQuery(q) pipeBuilder.producePipe(query, planContext, CompilationPhaseTracer.NO_TRACING) }) @@ -118,11 +118,11 @@ class RuleExecutablePlanBuilderTest .updates(DeletePropertyAction(variable, PropertyKey("foo"))) .returns(ReturnItem(Variable("x"), "x")) - val pipeBuilder = new LegacyExecutablePlanBuilder(new WrappedMonitors3_1(kernelMonitors), config, + val pipeBuilder = new LegacyExecutablePlanBuilder(new WrappedMonitors3_2(kernelMonitors), config, RewriterStepSequencer.newValidating, typeConverter = IdentityTypeConverter) val contextFactory = Neo4jTransactionalContextFactory.create(graph, locker) - val transactionalContext = TransactionalContextWrapperv3_1(contextFactory.newContext(QuerySource.UNKNOWN, tx, "X", Collections.emptyMap())) + val transactionalContext = TransactionalContextWrapperv3_2(contextFactory.newContext(QuerySource.UNKNOWN, tx, "X", Collections.emptyMap())) val queryContext = new TransactionBoundQueryContext(transactionalContext)(indexSearchMonitor) val pkId = queryContext.getPropertyKeyId("foo") val parsedQ = new FakePreparedSemanticQuery(q) @@ -148,10 +148,10 @@ class RuleExecutablePlanBuilderTest .where(HasLabel(Variable("x"), Label("Person"))) .returns(ReturnItem(Variable("x"), "x")) - val execPlanBuilder = new LegacyExecutablePlanBuilder(WrappedMonitors3_1(kernelMonitors), config, + val execPlanBuilder = new LegacyExecutablePlanBuilder(WrappedMonitors3_2(kernelMonitors), config, RewriterStepSequencer.newValidating, typeConverter = IdentityTypeConverter) val contextFactory = Neo4jTransactionalContextFactory.create(graph, locker) - val transactionalContext = TransactionalContextWrapperv3_1(contextFactory.newContext(QuerySource.UNKNOWN, tx, "X", Collections.emptyMap())) + val transactionalContext = TransactionalContextWrapperv3_2(contextFactory.newContext(QuerySource.UNKNOWN, tx, "X", Collections.emptyMap())) val queryContext = new TransactionBoundQueryContext(transactionalContext)(indexSearchMonitor) val labelId = queryContext.getLabelId("Person") val parsedQ = new FakePreparedSemanticQuery(q) @@ -181,7 +181,7 @@ class RuleExecutablePlanBuilderTest .returns(AllVariables()) val parsedQ = new FakePreparedSemanticQuery(q) - val pipeBuilder = new LegacyExecutablePlanBuilder(WrappedMonitors3_1(kernelMonitors), config, RewriterStepSequencer.newValidating, + val pipeBuilder = new LegacyExecutablePlanBuilder(WrappedMonitors3_2(kernelMonitors), config, RewriterStepSequencer.newValidating, typeConverter = IdentityTypeConverter) val pipe = pipeBuilder.producePipe(parsedQ, planContext, CompilationPhaseTracer.NO_TRACING).pipe @@ -210,7 +210,7 @@ class RuleExecutablePlanBuilderTest .returns(AllVariables()) val parsedQ = new FakePreparedSemanticQuery(q) - val pipeBuilder = new LegacyExecutablePlanBuilder(WrappedMonitors3_1(kernelMonitors), config, RewriterStepSequencer.newValidating, + val pipeBuilder = new LegacyExecutablePlanBuilder(WrappedMonitors3_2(kernelMonitors), config, RewriterStepSequencer.newValidating, typeConverter = IdentityTypeConverter) val pipe = pipeBuilder.producePipe(parsedQ, planContext, CompilationPhaseTracer.NO_TRACING).pipe @@ -238,7 +238,7 @@ class RuleExecutablePlanBuilderTest val parsedQ = new FakePreparedSemanticQuery(q) - val execPlanBuilder = new LegacyExecutablePlanBuilder(WrappedMonitors3_1(kernelMonitors), config, RewriterStepSequencer.newValidating, + val execPlanBuilder = new LegacyExecutablePlanBuilder(WrappedMonitors3_2(kernelMonitors), config, RewriterStepSequencer.newValidating, typeConverter = IdentityTypeConverter) val pipe = execPlanBuilder.producePipe(parsedQ, planContext, CompilationPhaseTracer.NO_TRACING).pipe @@ -263,7 +263,7 @@ class RuleExecutablePlanBuilderTest ) val parsedQ = new FakePreparedSemanticQuery(q) - val pipeBuilder = new LegacyExecutablePlanBuilder(WrappedMonitors3_1(kernelMonitors), config, RewriterStepSequencer.newValidating, + val pipeBuilder = new LegacyExecutablePlanBuilder(WrappedMonitors3_2(kernelMonitors), config, RewriterStepSequencer.newValidating, typeConverter = IdentityTypeConverter) // when diff --git a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/v3_2/TraversalMatcherTest.scala b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/v3_2/TraversalMatcherTest.scala index 7b6550b97ed34..c929175fc407b 100644 --- a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/v3_2/TraversalMatcherTest.scala +++ b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/v3_2/TraversalMatcherTest.scala @@ -25,7 +25,7 @@ import org.neo4j.cypher.internal.compiler.v3_2.pipes._ import org.neo4j.cypher.internal.compiler.v3_2.pipes.matching.SingleStep import org.neo4j.cypher.internal.compiler.v3_2.planDescription.Argument import org.neo4j.cypher.internal.frontend.v3_2.SemanticDirection.{BOTH, OUTGOING} -import org.neo4j.cypher.internal.spi.v3_1.{BidirectionalTraversalMatcher, MonoDirectionalTraversalMatcher} +import org.neo4j.cypher.internal.spi.v3_2.{BidirectionalTraversalMatcher, MonoDirectionalTraversalMatcher} import org.neo4j.graphdb.{Node, Path} class TraversalMatcherTest extends GraphDatabaseFunSuite with QueryStateTestSupport { diff --git a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/v3_2/codegen/CodeGeneratorTest.scala b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/v3_2/codegen/CodeGeneratorTest.scala index c211c21c9d21e..fb8ed41d8eb0b 100644 --- a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/v3_2/codegen/CodeGeneratorTest.scala +++ b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/v3_2/codegen/CodeGeneratorTest.scala @@ -34,8 +34,8 @@ import org.neo4j.cypher.internal.frontend.v3_2.ast._ import org.neo4j.cypher.internal.frontend.v3_2.symbols._ import org.neo4j.cypher.internal.frontend.v3_2.test_helpers.CypherFunSuite import org.neo4j.cypher.internal.frontend.v3_2.{ParameterNotFoundException, SemanticDirection, SemanticTable} -import org.neo4j.cypher.internal.spi.TransactionalContextWrapperv3_1 -import org.neo4j.cypher.internal.spi.v3_1.codegen.GeneratedQueryStructure +import org.neo4j.cypher.internal.spi.TransactionalContextWrapperv3_2 +import org.neo4j.cypher.internal.spi.v3_2.codegen.GeneratedQueryStructure import org.neo4j.graphdb.{Direction, Node, Relationship} import org.neo4j.kernel.api.ReadOperations import org.neo4j.kernel.impl.api.RelationshipVisitor @@ -961,7 +961,7 @@ class CodeGeneratorTest extends CypherFunSuite with LogicalPlanningTestSupport { }) private val queryContext = mock[QueryContext] - private val transactionalContext = mock[TransactionalContextWrapperv3_1] + private val transactionalContext = mock[TransactionalContextWrapperv3_2] private val ro = mock[ReadOperations] when(queryContext.transactionalContext).thenReturn(transactionalContext) when(transactionalContext.readOperations).thenReturn(ro) diff --git a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/v3_2/codegen/ir/CodeGenSugar.scala b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/v3_2/codegen/ir/CodeGenSugar.scala index 52113512c9206..3588a63e3da75 100644 --- a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/v3_2/codegen/ir/CodeGenSugar.scala +++ b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/v3_2/codegen/ir/CodeGenSugar.scala @@ -31,13 +31,13 @@ import org.neo4j.cypher.internal.compiler.v3_2.planner.logical.plans.LogicalPlan import org.neo4j.cypher.internal.compiler.v3_2.spi._ import org.neo4j.cypher.internal.compiler.v3_2.{CostBasedPlannerName, ExecutionMode, NormalMode, TaskCloser} import org.neo4j.cypher.internal.frontend.v3_2.SemanticTable -import org.neo4j.cypher.internal.spi.TransactionalContextWrapperv3_1 -import org.neo4j.cypher.internal.spi.v3_1.TransactionBoundQueryContext -import org.neo4j.cypher.internal.spi.v3_1.TransactionBoundQueryContext.IndexSearchMonitor -import org.neo4j.cypher.internal.spi.v3_1.codegen.GeneratedQueryStructure +import org.neo4j.cypher.internal.spi.TransactionalContextWrapperv3_2 +import org.neo4j.cypher.internal.spi.v3_2.TransactionBoundQueryContext +import org.neo4j.cypher.internal.spi.v3_2.TransactionBoundQueryContext.IndexSearchMonitor +import org.neo4j.cypher.internal.spi.v3_2.codegen.GeneratedQueryStructure import org.neo4j.graphdb.GraphDatabaseService import org.neo4j.kernel.GraphDatabaseQueryService -import org.neo4j.kernel.api.security.{AnonymousContext, SecurityContext} +import org.neo4j.kernel.api.security.AnonymousContext import org.neo4j.kernel.api.{KernelTransaction, Statement} import org.neo4j.kernel.impl.coreapi.PropertyContainerLocker import org.neo4j.kernel.impl.query.{Neo4jTransactionalContextFactory, QuerySource} @@ -68,7 +68,7 @@ trait CodeGenSugar extends MockitoSugar { try { val locker: PropertyContainerLocker = new PropertyContainerLocker val contextFactory = Neo4jTransactionalContextFactory.create(graphDb, locker) - val transactionalContext = TransactionalContextWrapperv3_1(contextFactory.newContext(QuerySource.UNKNOWN, tx, + val transactionalContext = TransactionalContextWrapperv3_2(contextFactory.newContext(QuerySource.UNKNOWN, tx, "no query text exists for this test", Collections.emptyMap())) val queryContext = new TransactionBoundQueryContext(transactionalContext)(mock[IndexSearchMonitor]) val result = plan.executionResultBuilder(queryContext, mode, tracer(mode), Map.empty, new TaskCloser) @@ -131,7 +131,7 @@ trait CodeGenSugar extends MockitoSugar { private def mockQueryContext() = { val qc = mock[QueryContext] - val transactionalContext = mock[TransactionalContextWrapperv3_1] + val transactionalContext = mock[TransactionalContextWrapperv3_2] val statement = mock[Statement] when(qc.transactionalContext).thenReturn(transactionalContext) when(transactionalContext.statement).thenReturn(statement) diff --git a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/v3_2/pipes/ActualCostCalculationTest.scala b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/v3_2/pipes/ActualCostCalculationTest.scala index ee34b8476d4cd..e327b5877d590 100644 --- a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/v3_2/pipes/ActualCostCalculationTest.scala +++ b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/v3_2/pipes/ActualCostCalculationTest.scala @@ -32,9 +32,9 @@ import org.neo4j.cypher.internal.compiler.v3_2.commands.values.TokenType.{Label import org.neo4j.cypher.internal.compiler.v3_2.devNullLogger import org.neo4j.cypher.internal.frontend.v3_2.test_helpers.CypherFunSuite import org.neo4j.cypher.internal.frontend.v3_2.{LabelId, PropertyKeyId, SemanticDirection, ast} -import org.neo4j.cypher.internal.spi.TransactionalContextWrapperv3_1 -import org.neo4j.cypher.internal.spi.v3_1.TransactionBoundQueryContext.IndexSearchMonitor -import org.neo4j.cypher.internal.spi.v3_1.{TransactionBoundPlanContext, TransactionBoundQueryContext} +import org.neo4j.cypher.internal.spi.TransactionalContextWrapperv3_2 +import org.neo4j.cypher.internal.spi.v3_2.TransactionBoundQueryContext.IndexSearchMonitor +import org.neo4j.cypher.internal.spi.v3_2.{TransactionBoundPlanContext, TransactionBoundQueryContext} import org.neo4j.cypher.javacompat.internal.GraphDatabaseCypherService import org.neo4j.graphdb._ import org.neo4j.graphdb.factory.GraphDatabaseFactory @@ -245,7 +245,7 @@ class ActualCostCalculationTest extends CypherFunSuite { graph.withTx { tx => val tc = transactionContext(graph, tx) - val tcWrapper = TransactionalContextWrapperv3_1(tc) + val tcWrapper = TransactionalContextWrapperv3_2(tc) val queryContext = new TransactionBoundQueryContext(tcWrapper)(mock[IndexSearchMonitor]) val state = QueryStateHelper.emptyWith(queryContext) for (x <- 0 to 25) { @@ -308,7 +308,7 @@ class ActualCostCalculationTest extends CypherFunSuite { private def indexSeek(graph: GraphDatabaseQueryService) = { graph.withTx { tx => - val transactionalContext = TransactionalContextWrapperv3_1(transactionContext(graph, tx)) + val transactionalContext = TransactionalContextWrapperv3_2(transactionContext(graph, tx)) val ctx = new TransactionBoundPlanContext(transactionalContext, devNullLogger) val literal = Literal(42) @@ -323,7 +323,7 @@ class ActualCostCalculationTest extends CypherFunSuite { private def indexScan(graph: GraphDatabaseQueryService): NodeIndexScanPipe = { graph.withTx { tx => - val transactionalContext = TransactionalContextWrapperv3_1(transactionContext(graph, tx)) + val transactionalContext = TransactionalContextWrapperv3_2(transactionContext(graph, tx)) val ctx = new TransactionBoundPlanContext(transactionalContext, devNullLogger) val labelId = ctx.getOptLabelId(LABEL.name()).get diff --git a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/spi/v3_1/TransactionBoundPlanContextTest.scala b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/spi/v3_1/TransactionBoundPlanContextTest.scala index 89314ee54055c..1f327eb1cd61a 100644 --- a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/spi/v3_1/TransactionBoundPlanContextTest.scala +++ b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/spi/v3_1/TransactionBoundPlanContextTest.scala @@ -21,10 +21,10 @@ package org.neo4j.cypher.internal.spi.v3_1 import java.util.Collections -import org.neo4j.cypher.internal.compiler.v3_2.devNullLogger -import org.neo4j.cypher.internal.compiler.v3_2.planner.logical.Cardinality +import org.neo4j.cypher.internal.compiler.v3_1.devNullLogger +import org.neo4j.cypher.internal.compiler.v3_1.planner.logical.Cardinality +import org.neo4j.cypher.internal.frontend.v3_1.{LabelId, RelTypeId} import org.neo4j.cypher.internal.frontend.v3_2.test_helpers.CypherFunSuite -import org.neo4j.cypher.internal.frontend.v3_2.{LabelId, RelTypeId} import org.neo4j.cypher.internal.spi.TransactionalContextWrapperv3_1 import org.neo4j.cypher.javacompat.internal.GraphDatabaseCypherService import org.neo4j.kernel.api.KernelTransaction.Type._ diff --git a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/spi/v3_1/TransactionBoundQueryContextTest.scala b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/spi/v3_1/TransactionBoundQueryContextTest.scala index 53d1a9d67f28c..f54255cb17fdf 100644 --- a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/spi/v3_1/TransactionBoundQueryContextTest.scala +++ b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/spi/v3_1/TransactionBoundQueryContextTest.scala @@ -23,8 +23,8 @@ import java.net.URL import java.util.Collections import org.mockito.Mockito._ -import org.neo4j.cypher.internal.compiler.v3_2.helpers.DynamicIterable -import org.neo4j.cypher.internal.frontend.v3_2.SemanticDirection +import org.neo4j.cypher.internal.compiler.v3_1.helpers.DynamicIterable +import org.neo4j.cypher.internal.frontend.v3_1.SemanticDirection import org.neo4j.cypher.internal.frontend.v3_2.test_helpers.CypherFunSuite import org.neo4j.cypher.internal.spi.TransactionalContextWrapperv3_1 import org.neo4j.cypher.internal.spi.v3_1.TransactionBoundQueryContext.IndexSearchMonitor diff --git a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/spi/v3_1/codegen/GeneratedMethodStructureTest.scala b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/spi/v3_1/codegen/GeneratedMethodStructureTest.scala index ff4bdc3307dcc..f54577760dedd 100644 --- a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/spi/v3_1/codegen/GeneratedMethodStructureTest.scala +++ b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/spi/v3_1/codegen/GeneratedMethodStructureTest.scala @@ -23,14 +23,14 @@ import java.util import org.neo4j.codegen.source.{Configuration, SourceCode} import org.neo4j.codegen.{CodeGenerationStrategy, CodeGenerator, Expression, MethodDeclaration} -import org.neo4j.cypher.internal.compiler.v3_2.codegen._ -import org.neo4j.cypher.internal.compiler.v3_2.codegen.ir.expressions.{CodeGenType, ReferenceType} -import org.neo4j.cypher.internal.compiler.v3_2.executionplan.{Provider, SuccessfulCloseable} -import org.neo4j.cypher.internal.compiler.v3_2.helpers._ -import org.neo4j.cypher.internal.compiler.v3_2.planDescription.InternalPlanDescription -import org.neo4j.cypher.internal.compiler.v3_2.{ExecutionMode, TaskCloser} +import org.neo4j.cypher.internal.compiler.v3_1.codegen._ +import org.neo4j.cypher.internal.compiler.v3_1.codegen.ir.expressions.{CodeGenType, ReferenceType} +import org.neo4j.cypher.internal.compiler.v3_1.executionplan.{Provider, SuccessfulCloseable} +import org.neo4j.cypher.internal.compiler.v3_1.helpers._ +import org.neo4j.cypher.internal.compiler.v3_1.planDescription.InternalPlanDescription +import org.neo4j.cypher.internal.compiler.v3_1.{ExecutionMode, TaskCloser} +import org.neo4j.cypher.internal.frontend.v3_1.{SemanticDirection, SemanticTable, symbols} import org.neo4j.cypher.internal.frontend.v3_2.test_helpers.CypherFunSuite -import org.neo4j.cypher.internal.frontend.v3_2.{SemanticDirection, SemanticTable, symbols} import org.neo4j.kernel.api.ReadOperations import org.neo4j.kernel.impl.api.store.RelationshipIterator import org.neo4j.kernel.impl.core.NodeManager diff --git a/community/kernel/src/main/java/org/neo4j/graphdb/factory/GraphDatabaseSettings.java b/community/kernel/src/main/java/org/neo4j/graphdb/factory/GraphDatabaseSettings.java index d81b5e18a643b..ac2d319869adf 100644 --- a/community/kernel/src/main/java/org/neo4j/graphdb/factory/GraphDatabaseSettings.java +++ b/community/kernel/src/main/java/org/neo4j/graphdb/factory/GraphDatabaseSettings.java @@ -19,56 +19,23 @@ */ package org.neo4j.graphdb.factory; -import java.io.File; -import java.util.List; -import java.util.stream.Collectors; - import org.neo4j.graphdb.config.Setting; import org.neo4j.helpers.AdvertisedSocketAddress; import org.neo4j.helpers.ListenSocketAddress; import org.neo4j.io.ByteUnit; -import org.neo4j.kernel.configuration.Config; -import org.neo4j.kernel.configuration.ConfigurationMigrator; -import org.neo4j.kernel.configuration.GraphDatabaseConfigurationMigrator; -import org.neo4j.kernel.configuration.Group; -import org.neo4j.kernel.configuration.GroupSettingSupport; -import org.neo4j.kernel.configuration.Internal; -import org.neo4j.kernel.configuration.Migrator; -import org.neo4j.kernel.configuration.Settings; -import org.neo4j.kernel.configuration.Title; +import org.neo4j.kernel.configuration.*; import org.neo4j.kernel.impl.cache.MonitorGc; import org.neo4j.kernel.impl.util.OsBeanUtil; import org.neo4j.logging.Level; +import java.io.File; +import java.util.List; +import java.util.stream.Collectors; + import static org.neo4j.graphdb.factory.GraphDatabaseSettings.BoltConnector.EncryptionLevel.OPTIONAL; import static org.neo4j.graphdb.factory.GraphDatabaseSettings.Connector.ConnectorType.BOLT; import static org.neo4j.kernel.configuration.GroupSettingSupport.enumerate; -import static org.neo4j.kernel.configuration.Settings.ANY; -import static org.neo4j.kernel.configuration.Settings.BOOLEAN; -import static org.neo4j.kernel.configuration.Settings.BYTES; -import static org.neo4j.kernel.configuration.Settings.DEFAULT; -import static org.neo4j.kernel.configuration.Settings.DOUBLE; -import static org.neo4j.kernel.configuration.Settings.DURATION; -import static org.neo4j.kernel.configuration.Settings.FALSE; -import static org.neo4j.kernel.configuration.Settings.INTEGER; -import static org.neo4j.kernel.configuration.Settings.LONG; -import static org.neo4j.kernel.configuration.Settings.NO_DEFAULT; -import static org.neo4j.kernel.configuration.Settings.PATH; -import static org.neo4j.kernel.configuration.Settings.STRING; -import static org.neo4j.kernel.configuration.Settings.STRING_LIST; -import static org.neo4j.kernel.configuration.Settings.TRUE; -import static org.neo4j.kernel.configuration.Settings.advertisedAddress; -import static org.neo4j.kernel.configuration.Settings.derivedSetting; -import static org.neo4j.kernel.configuration.Settings.illegalValueMessage; -import static org.neo4j.kernel.configuration.Settings.legacyFallback; -import static org.neo4j.kernel.configuration.Settings.list; -import static org.neo4j.kernel.configuration.Settings.listenAddress; -import static org.neo4j.kernel.configuration.Settings.matches; -import static org.neo4j.kernel.configuration.Settings.max; -import static org.neo4j.kernel.configuration.Settings.min; -import static org.neo4j.kernel.configuration.Settings.options; -import static org.neo4j.kernel.configuration.Settings.pathSetting; -import static org.neo4j.kernel.configuration.Settings.setting; +import static org.neo4j.kernel.configuration.Settings.*; /** * Settings for Neo4j. Use this with {@link GraphDatabaseBuilder}. @@ -124,7 +91,7 @@ public abstract class GraphDatabaseSettings @Description( "Set this to specify the default parser (language version)." ) public static final Setting cypher_parser_version = setting( "cypher.default_language_version", - options("2.3", "3.0", "3.1", DEFAULT ), DEFAULT ); + options("2.3", "3.1", "3.2", DEFAULT ), DEFAULT ); @Description( "Set this to specify the default planner for the default language version." ) public static final Setting cypher_planner = setting( diff --git a/community/kernel/src/test/java/org/neo4j/test/TestGraphDatabaseFactory.java b/community/kernel/src/test/java/org/neo4j/test/TestGraphDatabaseFactory.java index fc61aff4a411b..65cd4767e7123 100644 --- a/community/kernel/src/test/java/org/neo4j/test/TestGraphDatabaseFactory.java +++ b/community/kernel/src/test/java/org/neo4j/test/TestGraphDatabaseFactory.java @@ -19,13 +19,6 @@ */ package org.neo4j.test; -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.Collections; -import java.util.Map; - import org.neo4j.graphdb.GraphDatabaseService; import org.neo4j.graphdb.config.Setting; import org.neo4j.graphdb.factory.GraphDatabaseBuilder; @@ -35,17 +28,20 @@ import org.neo4j.io.fs.FileSystemAbstraction; import org.neo4j.kernel.GraphDatabaseDependencies; import org.neo4j.kernel.extension.KernelExtensionFactory; -import org.neo4j.kernel.impl.factory.CommunityEditionModule; -import org.neo4j.kernel.impl.factory.DatabaseInfo; -import org.neo4j.kernel.impl.factory.GraphDatabaseFacade; -import org.neo4j.kernel.impl.factory.GraphDatabaseFacadeFactory; -import org.neo4j.kernel.impl.factory.PlatformModule; +import org.neo4j.kernel.impl.factory.*; import org.neo4j.kernel.impl.logging.AbstractLogService; import org.neo4j.kernel.impl.logging.LogService; import org.neo4j.kernel.monitoring.Monitors; import org.neo4j.logging.LogProvider; import org.neo4j.logging.NullLogProvider; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Collections; +import java.util.Map; + import static org.neo4j.graphdb.factory.GraphDatabaseSettings.Connector.ConnectorType.BOLT; import static org.neo4j.graphdb.factory.GraphDatabaseSettings.boltConnector; @@ -75,7 +71,9 @@ public GraphDatabaseService newImpermanentDatabase( Map,String> confi GraphDatabaseBuilder builder = newImpermanentDatabaseBuilder(); for ( Map.Entry,String> entry : config.entrySet() ) { - builder.setConfig( entry.getKey(), entry.getValue() ); + Setting key = entry.getKey(); + String value = entry.getValue(); + builder.setConfig(key, value); } return builder.newGraphDatabase(); }