diff --git a/community/cypher/acceptance/src/test/scala/org/neo4j/internal/cypher/acceptance/FunctionsAcceptanceTest.scala b/community/cypher/acceptance/src/test/scala/org/neo4j/internal/cypher/acceptance/FunctionsAcceptanceTest.scala index bdd3344104c97..b1c9981a81e9a 100644 --- a/community/cypher/acceptance/src/test/scala/org/neo4j/internal/cypher/acceptance/FunctionsAcceptanceTest.scala +++ b/community/cypher/acceptance/src/test/scala/org/neo4j/internal/cypher/acceptance/FunctionsAcceptanceTest.scala @@ -647,7 +647,7 @@ class FunctionsAcceptanceTest extends ExecutionEngineFunSuite with NewPlannerTes val expected = createNode().getId // WHEN - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode("MATCH (n) RETURN id(n)") + val result = executeWithAllPlannersAndCompatibilityMode("MATCH (n) RETURN id(n)") // THEN result.toList should equal(List(Map("id(n)" -> expected))) @@ -659,7 +659,7 @@ class FunctionsAcceptanceTest extends ExecutionEngineFunSuite with NewPlannerTes val expected = relate(createNode(), createNode()).getId // WHEN - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode("MATCH ()-[r]->() RETURN id(r)") + val result = executeWithAllPlannersAndCompatibilityMode("MATCH ()-[r]->() RETURN id(r)") // THEN result.toList should equal(List(Map("id(r)" -> expected))) @@ -670,7 +670,7 @@ class FunctionsAcceptanceTest extends ExecutionEngineFunSuite with NewPlannerTes relate(createNode(), createNode(), "T") // WHEN - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode("MATCH ()-[r]->() RETURN type(r)") + val result = executeWithAllPlannersAndCompatibilityMode("MATCH ()-[r]->() RETURN type(r)") // THEN result.toList should equal(List(Map("type(r)" -> "T"))) @@ -683,7 +683,7 @@ class FunctionsAcceptanceTest extends ExecutionEngineFunSuite with NewPlannerTes relate(intermediate, createNode(), "T2") // WHEN - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode("MATCH ()-[r1]->()-[r2]->() RETURN type(r1), type(r2)") + val result = executeWithAllPlannersAndCompatibilityMode("MATCH ()-[r1]->()-[r2]->() RETURN type(r1), type(r2)") // THEN result.toList should equal(List(Map("type(r1)" -> "T1", "type(r2)" -> "T2"))) @@ -694,7 +694,7 @@ class FunctionsAcceptanceTest extends ExecutionEngineFunSuite with NewPlannerTes createNode() // WHEN - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode("MATCH (a) OPTIONAL MATCH (a)-[r:NOT_THERE]->() RETURN type(r)") + val result = executeWithAllPlannersAndCompatibilityMode("MATCH (a) OPTIONAL MATCH (a)-[r:NOT_THERE]->() RETURN type(r)") // THEN result.toList should equal(List(Map("type(r)" -> null))) @@ -705,7 +705,7 @@ class FunctionsAcceptanceTest extends ExecutionEngineFunSuite with NewPlannerTes relate(createNode(), createNode(), "T") // WHEN - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode("MATCH (a) OPTIONAL MATCH (a)-[r:T]->() RETURN type(r)") + val result = executeWithAllPlannersAndCompatibilityMode("MATCH (a) OPTIONAL MATCH (a)-[r:T]->() RETURN type(r)") // THEN result.toList should equal(List(Map("type(r)" -> "T"), Map("type(r)" -> null))) @@ -717,7 +717,6 @@ class FunctionsAcceptanceTest extends ExecutionEngineFunSuite with NewPlannerTes val query: String = "MATCH (a)-[r]->() WITH [r, 1] as coll RETURN [x in coll | type(x) ]" //Expect - a [SyntaxException] shouldBe thrownBy(eengine.execute(s"CYPHER runtime=compiled $query", Map.empty[String,Any], graph.session())) a [SyntaxException] shouldBe thrownBy(eengine.execute(s"CYPHER runtime=interpreted $query", Map.empty[String,Any], graph.session())) a [SyntaxException] shouldBe thrownBy(eengine.execute(s"CYPHER planner=cost $query", Map.empty[String,Any], graph.session())) a [SyntaxException] shouldBe thrownBy(eengine.execute(s"CYPHER planner=rule $query", Map.empty[String,Any], graph.session())) diff --git a/community/cypher/acceptance/src/test/scala/org/neo4j/internal/cypher/acceptance/MatchAcceptanceTest.scala b/community/cypher/acceptance/src/test/scala/org/neo4j/internal/cypher/acceptance/MatchAcceptanceTest.scala index 1e8254f4bef1c..23a82f4f9a4db 100644 --- a/community/cypher/acceptance/src/test/scala/org/neo4j/internal/cypher/acceptance/MatchAcceptanceTest.scala +++ b/community/cypher/acceptance/src/test/scala/org/neo4j/internal/cypher/acceptance/MatchAcceptanceTest.scala @@ -197,7 +197,7 @@ class MatchAcceptanceTest extends ExecutionEngineFunSuite with QueryStatisticsTe createNodes("A", "B", "C") relate("A" -> "KNOWS" -> "B") - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode("MATCH (a {name:'A'}),(c {name:'C'}) match (a)-->(b) return a,b,c").toSet + val result = executeWithAllPlannersAndCompatibilityMode("MATCH (a {name:'A'}),(c {name:'C'}) match (a)-->(b) return a,b,c").toSet result should equal (Set(Map("a" -> node("A"), "b" -> node("B"), "c" -> node("C")))) } @@ -323,7 +323,7 @@ class MatchAcceptanceTest extends ExecutionEngineFunSuite with QueryStatisticsTe relate(b, x1, "REL", "BX1") relate(b, x2, "REL", "BX2") - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode( """ + val result = executeWithAllPlannersAndCompatibilityMode( """ MATCH (a {name:'A'}), (b {name:'B'}) MATCH (a)-[rA]->(x)<-[rB]->(b) return x""") @@ -347,7 +347,7 @@ return x""") relate(c, x1, "REL", "CX1") relate(c, x2, "REL", "CX2") - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode( """ + val result = executeWithAllPlannersAndCompatibilityMode( """ MATCH (a {name:'A'}), (b {name:'B'}), (c {name:'C'}) match (a)-[rA]->(x), (b)-[rB]->(x), (c)-[rC]->(x) return x""") @@ -386,7 +386,7 @@ return x""") relate(c, g) relate(c, j) - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode( """ + val result = executeWithAllPlannersAndCompatibilityMode( """ MATCH (a {name:'a'}), (b {name:'b'}), (c {name:'c'}) match (a)-->(x), (b)-->(x), (c)-->(x) return x""") @@ -557,7 +557,7 @@ RETURN other""") val a = createNode() val b = createNode("Mark") relate(a, b) - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode( """ + val result = executeWithAllPlannersAndCompatibilityMode( """ MATCH (n)-->(x0) OPTIONAL MATCH (x0)-->(x1) WHERE x1.foo = 'bar' @@ -592,7 +592,7 @@ RETURN a.name""") val a = createNode() val b = createNode() - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode("match (n) return n") + val result = executeWithAllPlannersAndCompatibilityMode("match (n) return n") result.columnAs[Node]("n").toSet should equal (Set(a, b)) } @@ -600,7 +600,7 @@ RETURN a.name""") val a = createNode() val b = createNode() - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode("MATCH (a), (b) where a <> b return a,b") + val result = executeWithAllPlannersAndCompatibilityMode("MATCH (a), (b) where a <> b return a,b") result.toSet should equal (Set(Map("a" -> b, "b" -> a), Map("b" -> b, "a" -> a))) } @@ -612,7 +612,7 @@ RETURN a.name""") relate(a, b) relate(b, c) - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode("match (a)-->(b), (b)-->(b) return b") + val result = executeWithAllPlannersAndCompatibilityMode("match (a)-->(b), (b)-->(b) return b") result shouldBe 'isEmpty } @@ -625,7 +625,7 @@ RETURN a.name""") relate(a, b) - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode("match (a)-[r]->(a) return r") + val result = executeWithAllPlannersAndCompatibilityMode("match (a)-[r]->(a) return r") result.toList should equal (List(Map("r" -> r))) } @@ -671,7 +671,7 @@ return b val b = createNode() relate(a, b, "REL") - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode("match (a)-[:REL|:REL]->(b) return b").toList + val result = executeWithAllPlannersAndCompatibilityMode("match (a)-[:REL|:REL]->(b) return b").toList result should equal (List(Map("b" -> b))) } @@ -699,7 +699,7 @@ return b val n = createNode("foo" -> "bar") // when - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode("match (n) where n.foo = 'bar' return n") + val result = executeWithAllPlannersAndCompatibilityMode("match (n) where n.foo = 'bar' return n") // then result.toList should equal (List(Map("n" -> n))) @@ -755,7 +755,7 @@ return b test("should preserve the original matched values if optional match matches nothing") { val n = createNode() - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode("MATCH (n) OPTIONAL MATCH (n)-[:NOT_EXIST]->(x) RETURN n, x") + val result = executeWithAllPlannersAndCompatibilityMode("MATCH (n) OPTIONAL MATCH (n)-[:NOT_EXIST]->(x) RETURN n, x") result.toList should equal (List(Map("n" -> n, "x" -> null))) } @@ -808,7 +808,7 @@ return b relate(a, b2) // when - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode(s"MATCH (a)-->(b:foo) RETURN b") + val result = executeWithAllPlannersAndCompatibilityMode(s"MATCH (a)-->(b:foo) RETURN b") // THEN result.toList should equal (List(Map("b" -> b1))) @@ -822,7 +822,7 @@ return b relate(createLabeledNode("A"), createLabeledNode("A")) // when - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode(s"MATCH (a:A)-[r]->(b:B) RETURN r") + val result = executeWithAllPlannersAndCompatibilityMode(s"MATCH (a:A)-[r]->(b:B) RETURN r") // THEN result.toSet should equal (Set(Map("r" -> r))) @@ -839,7 +839,7 @@ return b createLabeledNode("C") // when - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode(s"MATCH (a:A:B:C) RETURN a") + val result = executeWithAllPlannersAndCompatibilityMode(s"MATCH (a:A:B:C) RETURN a") // THEN result.toList should equal (List(Map("a" -> n))) @@ -851,7 +851,7 @@ return b createLabeledNode("Foo") // when - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode(s"MATCH (n) RETURN (n:Foo)") + val result = executeWithAllPlannersAndCompatibilityMode(s"MATCH (n) RETURN (n:Foo)") // THEN result.toSet should equal (Set(Map("(n:Foo)" -> true), Map("(n:Foo)" -> false))) @@ -896,7 +896,7 @@ return b graph.createIndex("Person", "name") // when - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode("MATCH (n:Person)-->() USING INDEX n:Person(name) WHERE n.name = 'Jacob' RETURN n") + val result = executeWithAllPlannersAndCompatibilityMode("MATCH (n:Person)-->() USING INDEX n:Person(name) WHERE n.name = 'Jacob' RETURN n") // then result.toList should equal (List(Map("n" -> jake))) @@ -945,7 +945,7 @@ return b relate(jake, createNode()) // when - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode("MATCH (n:Person)-->() WHERE n.name = 'Jacob' RETURN n") + val result = executeWithAllPlannersAndCompatibilityMode("MATCH (n:Person)-->() WHERE n.name = 'Jacob' RETURN n") // then result.toList should equal (List(Map("n" -> jake))) @@ -968,7 +968,7 @@ return b relate(a, c) // when asked for a cartesian product of the same match twice - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode("match (a)-->(b) match (c)-->(d) return a,b,c,d") + val result = executeWithAllPlannersAndCompatibilityMode("match (a)-->(b) match (c)-->(d) return a,b,c,d") // then we should find 2 x 2 = 4 result matches @@ -1031,7 +1031,7 @@ return b graph.createIndex("Label", "property") // when - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode("match (a:Label)-->(b:Label) where a.property = b.property return a, b") + val result = executeWithAllPlannersAndCompatibilityMode("match (a:Label)-->(b:Label) where a.property = b.property return a, b") // then does not throw exceptions result.toList should equal (List(Map("a" -> a, "b" -> b))) @@ -1176,7 +1176,7 @@ return b relate(b, c, "B") // when - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode("match (a)-[r1:A]->(x)-[r2:B]->(a) return a.name") + val result = executeWithAllPlannersAndCompatibilityMode("match (a)-[r1:A]->(x)-[r2:B]->(a) return a.name") // then does not throw exceptions assert(result.toList === List( @@ -1194,7 +1194,7 @@ return b relate(b, c, "B") // when - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode("match (a)-[:A]->(b), (b)-[:B]->(a) return a.name") + val result = executeWithAllPlannersAndCompatibilityMode("match (a)-[:A]->(b), (b)-[:B]->(a) return a.name") // then does not throw exceptions assert(result.toList === List( @@ -1675,7 +1675,7 @@ return b //WHEN val first = updateWithBothPlannersAndCompatibilityMode(query).length val second = updateWithBothPlannersAndCompatibilityMode(query).length - val check = executeWithAllPlannersAndRuntimesAndCompatibilityMode("MATCH (f:Folder) RETURN f.name").toSet + val check = executeWithAllPlannersAndCompatibilityMode("MATCH (f:Folder) RETURN f.name").toSet //THEN first should equal(second) @@ -1708,7 +1708,7 @@ return b val first = updateWithBothPlannersAndCompatibilityMode(query).length val second = updateWithBothPlannersAndCompatibilityMode(query).length - val check = executeWithAllPlannersAndRuntimesAndCompatibilityMode("MATCH (f:Folder) RETURN f.name").toSet + val check = executeWithAllPlannersAndCompatibilityMode("MATCH (f:Folder) RETURN f.name").toSet //THEN first should equal(second) @@ -1878,7 +1878,7 @@ return b val query = "MATCH (a) RETURN a.bar" - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode(query).toList + val result = executeWithAllPlannersAndCompatibilityMode(query).toList result should equal(List(Map("a.bar" -> null))) } @@ -1888,7 +1888,7 @@ return b val query = "MATCH (a) RETURN a.prop" - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode(query).toComparableResult + val result = executeWithAllPlannersAndCompatibilityMode(query).toComparableResult result should equal(List(asResult(props, "a"))) } @@ -1897,7 +1897,7 @@ return b val query = "MATCH (a)-[r]->(b) RETURN r.prop" - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode(query).toComparableResult + val result = executeWithAllPlannersAndCompatibilityMode(query).toComparableResult result should equal(List(asResult(Map("prop" -> 1), "r"))) } @@ -1907,7 +1907,7 @@ return b val query = "MATCH (a)-[r]->(b) RETURN a.nodeProp, r.relProp" - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode(query).toComparableResult + val result = executeWithAllPlannersAndCompatibilityMode(query).toComparableResult result should equal(List(asResult(Map("nodeProp" -> 1), "a") ++ asResult(Map("relProp" -> 2), "r"))) } @@ -1917,7 +1917,7 @@ return b val query = "MATCH (a)-[r]->(b) RETURN a AS FOO, r AS BAR" - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode(query).toComparableResult + val result = executeWithAllPlannersAndCompatibilityMode(query).toComparableResult result should equal(List(Map("FOO" -> a, "BAR" -> r))) } @@ -1926,7 +1926,7 @@ return b val query = "MATCH (a)-[r]->(b) RETURN r.foo" - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode(query).toComparableResult + val result = executeWithAllPlannersAndCompatibilityMode(query).toComparableResult result should equal(List(Map("r.foo" -> null))) } @@ -1940,14 +1940,14 @@ return b val query = "MATCH (a) RETURN a.name, a.age, a.seasons" - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode(query).toComparableResult + val result = executeWithAllPlannersAndCompatibilityMode(query).toComparableResult result should equal(List(asResult(props, "a"))) } test("adding a property and a literal is supported in new runtime") { val props = Map("prop" -> 1) createNode(props) - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode("MATCH (a) RETURN a.prop + 1 AS FOO").toComparableResult + val result = executeWithAllPlannersAndCompatibilityMode("MATCH (a) RETURN a.prop + 1 AS FOO").toComparableResult result should equal(List(Map("FOO" -> 2))) } @@ -1955,7 +1955,7 @@ return b test("adding arrays is supported in new runtime") { val props = Map("prop1" -> Array(1,2,3), "prop2" -> Array(4, 5)) createNode(props) - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode("MATCH (a) RETURN a.prop1 + a.prop2 AS FOO").toComparableResult + val result = executeWithAllPlannersAndCompatibilityMode("MATCH (a) RETURN a.prop1 + a.prop2 AS FOO").toComparableResult result should equal(List(Map("FOO" -> List(1, 2, 3, 4, 5)))) } @@ -2007,7 +2007,7 @@ return b val node1 = createNode() val node2 = createNode() val rel = relate(node1, node2) - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode("match (n)-[r]->(m) return [n, r, m] as r").toComparableResult + val result = executeWithAllPlannersAndCompatibilityMode("match (n)-[r]->(m) return [n, r, m] as r").toComparableResult result should equal(Seq(Map("r" -> Seq(node1, rel, node2)))) } @@ -2016,7 +2016,7 @@ return b val node1 = createNode() val node2 = createNode() val rel = relate(node1, node2) - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode("match (n)-[r]->(m) return {node1: n, rel: r, node2: m} as m").toComparableResult + val result = executeWithAllPlannersAndCompatibilityMode("match (n)-[r]->(m) return {node1: n, rel: r, node2: m} as m").toComparableResult result should equal(Seq(Map("m" -> Map("node1" -> node1, "rel" -> rel, "node2" -> node2)))) } @@ -2081,7 +2081,7 @@ return b } test("columns should be in the provided order") { - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode("MATCH (p),(o),(n),(t),(u),(s) RETURN p,o,n,t,u,s") + val result = executeWithAllPlannersAndCompatibilityMode("MATCH (p),(o),(n),(t),(u),(s) RETURN p,o,n,t,u,s") result.columns should equal(List("p", "o", "n", "t", "u", "s")) } diff --git a/community/cypher/acceptance/src/test/scala/org/neo4j/internal/cypher/acceptance/OptionalMatchAcceptanceTest.scala b/community/cypher/acceptance/src/test/scala/org/neo4j/internal/cypher/acceptance/OptionalMatchAcceptanceTest.scala index 3bcaf84893019..75a7544aeb795 100644 --- a/community/cypher/acceptance/src/test/scala/org/neo4j/internal/cypher/acceptance/OptionalMatchAcceptanceTest.scala +++ b/community/cypher/acceptance/src/test/scala/org/neo4j/internal/cypher/acceptance/OptionalMatchAcceptanceTest.scala @@ -19,7 +19,7 @@ */ package org.neo4j.internal.cypher.acceptance -import org.neo4j.cypher.{NewPlannerTestSupport, ExecutionEngineFunSuite} +import org.neo4j.cypher.{ExecutionEngineFunSuite, NewPlannerTestSupport} import org.neo4j.graphdb._ class OptionalMatchAcceptanceTest extends ExecutionEngineFunSuite with NewPlannerTestSupport { @@ -52,12 +52,12 @@ class OptionalMatchAcceptanceTest extends ExecutionEngineFunSuite with NewPlanne } test("predicates on optional matches should be respected") { - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode("match (n:Single) optional match (n)-[r]-(m) where m.prop = 42 return m") + val result = executeWithAllPlannersAndCompatibilityMode("match (n:Single) optional match (n)-[r]-(m) where m.prop = 42 return m") assert(result.toList === List(Map("m" -> nodeA))) } test("has label on null should evaluate to null") { - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode("match (n:Single) optional match (n)-[r:TYPE]-(m) return m:TYPE") + val result = executeWithAllPlannersAndCompatibilityMode("match (n:Single) optional match (n)-[r:TYPE]-(m) return m:TYPE") assert(result.toList === List(Map("m:TYPE" -> null))) } @@ -84,7 +84,7 @@ class OptionalMatchAcceptanceTest extends ExecutionEngineFunSuite with NewPlanne } test("optional matching between two found nodes behaves as expected") { - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode( + val result = executeWithAllPlannersAndCompatibilityMode( """match (a:A), (b:C) |optional match (x)-->(b) |return x""".stripMargin) @@ -103,7 +103,7 @@ class OptionalMatchAcceptanceTest extends ExecutionEngineFunSuite with NewPlanne relate(x2, b1) relate(x2, b2) - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode("MATCH (a:X) OPTIONAL MATCH (a)-->(b:Y) RETURN b") + val result = executeWithAllPlannersAndCompatibilityMode("MATCH (a:X) OPTIONAL MATCH (a)-->(b:Y) RETURN b") result.toSet should equal(Set(Map("b" -> null), Map("b" -> b1), Map("b" -> b2))) } diff --git a/community/cypher/acceptance/src/test/scala/org/neo4j/internal/cypher/acceptance/ReturnAcceptanceTest.scala b/community/cypher/acceptance/src/test/scala/org/neo4j/internal/cypher/acceptance/ReturnAcceptanceTest.scala index 9469ec7fd154a..2bf09ba4d53be 100644 --- a/community/cypher/acceptance/src/test/scala/org/neo4j/internal/cypher/acceptance/ReturnAcceptanceTest.scala +++ b/community/cypher/acceptance/src/test/scala/org/neo4j/internal/cypher/acceptance/ReturnAcceptanceTest.scala @@ -78,7 +78,7 @@ class ReturnAcceptanceTest extends ExecutionEngineFunSuite with CustomMatchers w createNode() createNode() createNode() - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode("match (n) return n limit 0") + val result = executeWithAllPlannersAndCompatibilityMode("match (n) return n limit 0") result should be(empty) } @@ -139,7 +139,7 @@ order by a.age""").toList) } test("long or double") { - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode("return 1, 1.5").toList.head + val result = executeWithAllPlannersAndCompatibilityMode("return 1, 1.5").toList.head result("1") should haveType[java.lang.Long] result("1.5") should haveType[java.lang.Double] @@ -240,13 +240,13 @@ order by a.age""").toList) test("array prop output") { createNode("foo" -> Array(1, 2, 3)) - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode("match (n) return n").dumpToString() + val result = executeWithAllPlannersAndCompatibilityMode("match (n) return n").dumpToString() result should include ("[1,2,3]") } test("map output") { - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode("return {a:1, b:'foo'}").dumpToString() + val result = executeWithAllPlannersAndCompatibilityMode("return {a:1, b:'foo'}").dumpToString() result should ( include ("""{a -> 1, b -> "foo"}""") or include ("""{b -> "foo", a -> 1}""") ) } @@ -323,7 +323,7 @@ order by a.age""").toList) } test("allow queries with only return") { - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode("RETURN 'Andres'").toList + val result = executeWithAllPlannersAndCompatibilityMode("RETURN 'Andres'").toList result should equal(List(Map("'Andres'" -> "Andres"))) } @@ -348,7 +348,7 @@ order by a.age""").toList) test("should be able to alias expressions") { createNode("id" -> 42) - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode("match (a) return a.id as a, a.id") + val result = executeWithAllPlannersAndCompatibilityMode("match (a) return a.id as a, a.id") result.toList should equal(List(Map("a" -> 42, "a.id" -> 42))) } @@ -397,19 +397,19 @@ order by a.age""").toList) } test("compiled runtime should support literal expressions") { - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode("RETURN 1") + val result = executeWithAllPlannersAndCompatibilityMode("RETURN 1") result.toList should equal(List(Map("1" -> 1))) } test("compiled runtime should support addition of collections") { - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode("RETURN [1,2,3] + [4, 5] AS FOO") + val result = executeWithAllPlannersAndCompatibilityMode("RETURN [1,2,3] + [4, 5] AS FOO") result.toComparableResult should equal(List(Map("FOO" -> List(1, 2, 3, 4, 5)))) } test("compiled runtime should support addition of item to collection") { - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode("""RETURN [1,2,3] + 4 AS FOO""") + val result = executeWithAllPlannersAndCompatibilityMode("""RETURN [1,2,3] + 4 AS FOO""") result.toComparableResult should equal(List(Map("FOO" -> List(1, 2, 3, 4)))) } @@ -417,7 +417,7 @@ order by a.age""").toList) test("Should return correct scala objects") { val query = "RETURN {uid: 'foo'} AS params" - val rows = executeWithAllPlannersAndRuntimesAndCompatibilityMode(query).columnAs[Map[String, Any]]("params").toList + val rows = executeWithAllPlannersAndCompatibilityMode(query).columnAs[Map[String, Any]]("params").toList rows.head should equal(Map("uid" -> "foo")) } diff --git a/community/cypher/acceptance/src/test/scala/org/neo4j/internal/cypher/acceptance/UniqueIndexAcceptanceTest.scala b/community/cypher/acceptance/src/test/scala/org/neo4j/internal/cypher/acceptance/UniqueIndexAcceptanceTest.scala index 45c78802d5065..b387bd8258966 100644 --- a/community/cypher/acceptance/src/test/scala/org/neo4j/internal/cypher/acceptance/UniqueIndexAcceptanceTest.scala +++ b/community/cypher/acceptance/src/test/scala/org/neo4j/internal/cypher/acceptance/UniqueIndexAcceptanceTest.scala @@ -33,7 +33,7 @@ class UniqueIndexAcceptanceTest extends ExecutionEngineFunSuite with NewPlannerT graph.createConstraint("Person", "name") //WHEN - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode("MATCH (n:Person)-->() USING INDEX n:Person(name) WHERE n.name IN ['Jacob'] RETURN n") + val result = executeWithAllPlannersAndCompatibilityMode("MATCH (n:Person)-->() USING INDEX n:Person(name) WHERE n.name IN ['Jacob'] RETURN n") //THEN result.toList should equal (List(Map("n" -> jake))) @@ -49,7 +49,7 @@ class UniqueIndexAcceptanceTest extends ExecutionEngineFunSuite with NewPlannerT graph.createConstraint("Person", "name") //WHEN - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode("MATCH (n:Person)-->() USING INDEX n:Person(name) WHERE n.name IN ['Jacob','Jacob'] RETURN n") + val result = executeWithAllPlannersAndCompatibilityMode("MATCH (n:Person)-->() USING INDEX n:Person(name) WHERE n.name IN ['Jacob','Jacob'] RETURN n") //THEN result.toList should equal (List(Map("n" -> jake))) @@ -65,7 +65,7 @@ class UniqueIndexAcceptanceTest extends ExecutionEngineFunSuite with NewPlannerT graph.createConstraint("Person", "name") //WHEN - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode("MATCH (n:Person)-->() USING INDEX n:Person(name) WHERE n.name IN [] RETURN n") + val result = executeWithAllPlannersAndCompatibilityMode("MATCH (n:Person)-->() USING INDEX n:Person(name) WHERE n.name IN [] RETURN n") //THEN result.toList should equal (List()) @@ -81,7 +81,7 @@ class UniqueIndexAcceptanceTest extends ExecutionEngineFunSuite with NewPlannerT graph.createConstraint("Person", "name") //WHEN - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode("MATCH (n:Person)-->() USING INDEX n:Person(name) WHERE n.name IN null RETURN n") + val result = executeWithAllPlannersAndCompatibilityMode("MATCH (n:Person)-->() USING INDEX n:Person(name) WHERE n.name IN null RETURN n") //THEN result.toList should equal (List()) @@ -97,7 +97,7 @@ class UniqueIndexAcceptanceTest extends ExecutionEngineFunSuite with NewPlannerT graph.createConstraint("Person", "name") //WHEN - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode("MATCH (n:Person)-->() USING INDEX n:Person(name) WHERE n.name IN {coll} RETURN n","coll"->List("Jacob")) + val result = executeWithAllPlannersAndCompatibilityMode("MATCH (n:Person)-->() USING INDEX n:Person(name) WHERE n.name IN {coll} RETURN n","coll"->List("Jacob")) //THEN result.toList should equal (List(Map("n" -> jake))) @@ -113,7 +113,7 @@ class UniqueIndexAcceptanceTest extends ExecutionEngineFunSuite with NewPlannerT graph.createConstraint("Person", "name") //WHEN - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode("MATCH (n:Person)-->() USING INDEX n:Person(name) WHERE n.name IN {coll} RETURN n","coll"->List("Jacob")) + val result = executeWithAllPlannersAndCompatibilityMode("MATCH (n:Person)-->() USING INDEX n:Person(name) WHERE n.name IN {coll} RETURN n","coll"->List("Jacob")) //THEN result should use("NodeUniqueIndexSeek") diff --git a/community/cypher/acceptance/src/test/scala/org/neo4j/internal/cypher/acceptance/UsingAcceptanceTest.scala b/community/cypher/acceptance/src/test/scala/org/neo4j/internal/cypher/acceptance/UsingAcceptanceTest.scala index 992f7e6f8bdca..67577405263a7 100644 --- a/community/cypher/acceptance/src/test/scala/org/neo4j/internal/cypher/acceptance/UsingAcceptanceTest.scala +++ b/community/cypher/acceptance/src/test/scala/org/neo4j/internal/cypher/acceptance/UsingAcceptanceTest.scala @@ -78,7 +78,7 @@ class UsingAcceptanceTest extends ExecutionEngineFunSuite with NewPlannerTestSup } test("scan hints are handled by ronja") { - executeWithAllPlannersAndRuntimesAndCompatibilityMode("match (n:Person) using scan n:Person return n").toList + executeWithAllPlannersAndCompatibilityMode("match (n:Person) using scan n:Person return n").toList } test("fail when equality checks are done with OR") { @@ -178,7 +178,7 @@ class UsingAcceptanceTest extends ExecutionEngineFunSuite with NewPlannerTestSup graph.createIndex("Person", "name") //WHEN - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode("MATCH (n:Person)-->() USING INDEX n:Person(name) WHERE n.name IN ['Jacob'] RETURN n") + val result = executeWithAllPlannersAndCompatibilityMode("MATCH (n:Person)-->() USING INDEX n:Person(name) WHERE n.name IN ['Jacob'] RETURN n") //THEN result.toList should equal(List(Map("n" -> jake))) @@ -194,7 +194,7 @@ class UsingAcceptanceTest extends ExecutionEngineFunSuite with NewPlannerTestSup graph.createIndex("Person", "name") //WHEN - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode("MATCH (n:Person)-->() USING INDEX n:Person(name) WHERE n.name IN ['Jacob','Jacob'] RETURN n") + val result = executeWithAllPlannersAndCompatibilityMode("MATCH (n:Person)-->() USING INDEX n:Person(name) WHERE n.name IN ['Jacob','Jacob'] RETURN n") //THEN result.toList should equal(List(Map("n" -> jake))) @@ -210,7 +210,7 @@ class UsingAcceptanceTest extends ExecutionEngineFunSuite with NewPlannerTestSup graph.createIndex("Person", "name") //WHEN - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode("MATCH (n:Person)-->() USING INDEX n:Person(name) WHERE n.name IN [] RETURN n") + val result = executeWithAllPlannersAndCompatibilityMode("MATCH (n:Person)-->() USING INDEX n:Person(name) WHERE n.name IN [] RETURN n") //THEN result.toList should equal(List()) @@ -226,7 +226,7 @@ class UsingAcceptanceTest extends ExecutionEngineFunSuite with NewPlannerTestSup graph.createIndex("Person", "name") //WHEN - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode("MATCH (n:Person)-->() USING INDEX n:Person(name) WHERE n.name IN null RETURN n") + val result = executeWithAllPlannersAndCompatibilityMode("MATCH (n:Person)-->() USING INDEX n:Person(name) WHERE n.name IN null RETURN n") //THEN result.toList should equal(List()) @@ -242,7 +242,7 @@ class UsingAcceptanceTest extends ExecutionEngineFunSuite with NewPlannerTestSup graph.createIndex("Person", "name") //WHEN - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode("MATCH (n:Person)-->() USING INDEX n:Person(name) WHERE n.name IN {coll} RETURN n", "coll" -> List("Jacob")) + val result = executeWithAllPlannersAndCompatibilityMode("MATCH (n:Person)-->() USING INDEX n:Person(name) WHERE n.name IN {coll} RETURN n", "coll" -> List("Jacob")) //THEN result.toList should equal(List(Map("n" -> jake))) diff --git a/community/cypher/acceptance/src/test/scala/org/neo4j/internal/cypher/acceptance/WithAcceptanceTest.scala b/community/cypher/acceptance/src/test/scala/org/neo4j/internal/cypher/acceptance/WithAcceptanceTest.scala index b25b01a60e4b8..5863e5065cc06 100644 --- a/community/cypher/acceptance/src/test/scala/org/neo4j/internal/cypher/acceptance/WithAcceptanceTest.scala +++ b/community/cypher/acceptance/src/test/scala/org/neo4j/internal/cypher/acceptance/WithAcceptanceTest.scala @@ -28,7 +28,7 @@ class WithAcceptanceTest extends ExecutionEngineFunSuite with NewPlannerTestSupp val b = createNode() relate(a, b) - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode( + val result = executeWithAllPlannersAndCompatibilityMode( "MATCH (a) WITH a MATCH (a)-->(b) RETURN *" ) result.toList should equal(List(Map("a" -> a, "b" -> b))) @@ -51,7 +51,7 @@ class WithAcceptanceTest extends ExecutionEngineFunSuite with NewPlannerTestSupp val a = createNode() val b = createNode() - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode( + val result = executeWithAllPlannersAndCompatibilityMode( "MATCH (a) WITH a MATCH (b) RETURN *" ) result.toSet should equal(Set( diff --git a/community/cypher/compatibility-suite/src/test/java/cypher/FeatureSuiteTest.java b/community/cypher/compatibility-suite/src/test/java/cypher/FeatureSuiteTest.java index 33dc97ede8693..610be67d9b411 100644 --- a/community/cypher/compatibility-suite/src/test/java/cypher/FeatureSuiteTest.java +++ b/community/cypher/compatibility-suite/src/test/java/cypher/FeatureSuiteTest.java @@ -48,16 +48,4 @@ public static class RuleInterpreted public static class CostInterpreted { } - - // The compiled runtime is not officially supported, and it fails on running these tests -// @RunWith( Cucumber.class ) -// @CucumberOptions( plugin = { -// "pretty", "html:target/cost-compiled", -// "cypher.cucumber.reporter.CypherResultReporter:target/cost-compiled", -// "cypher.cucumber.db.DatabaseProvider:target/dbs", -// "cypher.cucumber.db.DatabaseConfigProvider:/cypher/db/config/cost-compiled.json", -// } ) -// public static class CostCompiled -// { -// } } diff --git a/community/cypher/compatibility-suite/src/test/resources/cypher/db/config/cost-compiled.json b/community/cypher/compatibility-suite/src/test/resources/cypher/db/config/cost-compiled.json deleted file mode 100644 index 15c5341800dd8..0000000000000 --- a/community/cypher/compatibility-suite/src/test/resources/cypher/db/config/cost-compiled.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "planner" : "cost", - "runtime" : "compiled" -} diff --git a/community/cypher/cypher-compiler-3.0/src/main/java/org/neo4j/cypher/internal/compiler/v3_0/codegen/ResultRowImpl.java b/community/cypher/cypher-compiler-3.0/src/main/java/org/neo4j/cypher/internal/compiler/v3_0/ResultRowImpl.java similarity index 98% rename from community/cypher/cypher-compiler-3.0/src/main/java/org/neo4j/cypher/internal/compiler/v3_0/codegen/ResultRowImpl.java rename to community/cypher/cypher-compiler-3.0/src/main/java/org/neo4j/cypher/internal/compiler/v3_0/ResultRowImpl.java index 4ddb58897fe2e..1bdc973b61bfd 100644 --- a/community/cypher/cypher-compiler-3.0/src/main/java/org/neo4j/cypher/internal/compiler/v3_0/codegen/ResultRowImpl.java +++ b/community/cypher/cypher-compiler-3.0/src/main/java/org/neo4j/cypher/internal/compiler/v3_0/ResultRowImpl.java @@ -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.compiler.v3_0.codegen; +package org.neo4j.cypher.internal.compiler.v3_0; import java.util.HashMap; import java.util.Map; @@ -109,3 +109,4 @@ private T get( String key, Class type ) } } + diff --git a/community/cypher/cypher-compiler-3.0/src/main/java/org/neo4j/cypher/internal/compiler/v3_0/codegen/QueryExecutionTracer.java b/community/cypher/cypher-compiler-3.0/src/main/java/org/neo4j/cypher/internal/compiler/v3_0/codegen/QueryExecutionTracer.java deleted file mode 100644 index 621618403b1e4..0000000000000 --- a/community/cypher/cypher-compiler-3.0/src/main/java/org/neo4j/cypher/internal/compiler/v3_0/codegen/QueryExecutionTracer.java +++ /dev/null @@ -1,36 +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.compiler.v3_0.codegen; - -import org.neo4j.cypher.internal.compiler.v3_0.planDescription.Id; - -public interface QueryExecutionTracer -{ - QueryExecutionEvent executeOperator( Id queryId ); - - QueryExecutionTracer NONE = new QueryExecutionTracer() - { - @Override - public QueryExecutionEvent executeOperator( Id queryId ) - { - return QueryExecutionEvent.NONE; - } - }; -} diff --git a/community/cypher/cypher-compiler-3.0/src/main/java/org/neo4j/cypher/internal/compiler/v3_0/codegen/profiling/ProfilingTracer.java b/community/cypher/cypher-compiler-3.0/src/main/java/org/neo4j/cypher/internal/compiler/v3_0/codegen/profiling/ProfilingTracer.java deleted file mode 100644 index dcdb3a6fa6a76..0000000000000 --- a/community/cypher/cypher-compiler-3.0/src/main/java/org/neo4j/cypher/internal/compiler/v3_0/codegen/profiling/ProfilingTracer.java +++ /dev/null @@ -1,166 +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.compiler.v3_0.codegen.profiling; - -import java.util.HashMap; -import java.util.Map; - -import org.neo4j.cypher.internal.compiler.v3_0.codegen.QueryExecutionEvent; -import org.neo4j.cypher.internal.compiler.v3_0.codegen.QueryExecutionTracer; -import org.neo4j.cypher.internal.compiler.v3_0.planDescription.Id; - -public class ProfilingTracer implements QueryExecutionTracer -{ - public interface ProfilingInformation - { - long time(); - long dbHits(); - long rows(); - } - - public interface Clock - { - long nanoTime(); - - Clock SYSTEM_TIMER = new Clock() - { - @Override - public long nanoTime() - { - return System.nanoTime(); - } - }; - } - - private static final Data ZERO = new Data(); - - private final Clock clock; - private final Map data = new HashMap<>(); - - public ProfilingTracer() - { - this( Clock.SYSTEM_TIMER ); - } - - ProfilingTracer( Clock clock ) - { - this.clock = clock; - } - - public ProfilingInformation get( Id query ) - { - Data value = data.get( query ); - return value == null ? ZERO : value; - } - - public long timeOf( Id query ) - { - return get( query ).time(); - } - - public long dbHitsOf( Id query ) - { - return get( query ).dbHits(); - } - - public long rowsOf( Id query ) - { - return get( query ).rows(); - } - - @Override - public QueryExecutionEvent executeOperator( Id queryId ) - { - Data data = this.data.get( queryId ); - if ( data == null && queryId != null ) - { - this.data.put( queryId, data = new Data() ); - } - return new ExecutionEvent( clock, data ); - } - - private static class ExecutionEvent implements QueryExecutionEvent - { - private final long start; - private final Clock clock; - private final Data data; - private long hitCount; - private long rowCount; - - public ExecutionEvent( Clock clock, Data data ) - { - this.clock = clock; - this.data = data; - this.start = clock.nanoTime(); - } - - @Override - public void close() - { - long executionTime = clock.nanoTime() - start; - if ( data != null ) - { - data.update( executionTime, hitCount, rowCount ); - } - } - - @Override - public void dbHit() - { - hitCount++; - } - - @Override - public void row() - { - rowCount++; - } - } - - private static class Data implements ProfilingInformation - { - private long time, hits, rows; - - public void update( long time, long hits, long rows ) - { - this.time += time; - this.hits += hits; - this.rows += rows; - } - - @Override - public long time() - { - return time; - } - - @Override - public long dbHits() - { - return hits; - } - - @Override - public long rows() - { - return rows; - } - } -} diff --git a/community/cypher/cypher-compiler-3.0/src/main/java/org/neo4j/cypher/internal/compiler/v3_0/executionplan/GeneratedQuery.java b/community/cypher/cypher-compiler-3.0/src/main/java/org/neo4j/cypher/internal/compiler/v3_0/executionplan/GeneratedQuery.java deleted file mode 100644 index 0bb40336c941b..0000000000000 --- a/community/cypher/cypher-compiler-3.0/src/main/java/org/neo4j/cypher/internal/compiler/v3_0/executionplan/GeneratedQuery.java +++ /dev/null @@ -1,39 +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.compiler.v3_0.executionplan; - -import java.util.Map; - -import org.neo4j.cypher.internal.compiler.v3_0.ExecutionMode; -import org.neo4j.cypher.internal.compiler.v3_0.TaskCloser; -import org.neo4j.cypher.internal.compiler.v3_0.codegen.QueryExecutionTracer; -import org.neo4j.cypher.internal.compiler.v3_0.planDescription.InternalPlanDescription; -import org.neo4j.cypher.internal.compiler.v3_0.spi.QueryContext; - -public interface GeneratedQuery -{ - GeneratedQueryExecution execute( - TaskCloser closer, - QueryContext queryContext, - ExecutionMode executionMode, - Provider description, - QueryExecutionTracer tracer, - Map params ); -} diff --git a/community/cypher/cypher-compiler-3.0/src/main/java/org/neo4j/cypher/internal/compiler/v3_0/executionplan/GeneratedQueryExecution.java b/community/cypher/cypher-compiler-3.0/src/main/java/org/neo4j/cypher/internal/compiler/v3_0/executionplan/GeneratedQueryExecution.java deleted file mode 100644 index da5d97e45693b..0000000000000 --- a/community/cypher/cypher-compiler-3.0/src/main/java/org/neo4j/cypher/internal/compiler/v3_0/executionplan/GeneratedQueryExecution.java +++ /dev/null @@ -1,39 +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.compiler.v3_0.executionplan; - -import java.util.List; - -import org.neo4j.cypher.internal.compiler.v3_0.ExecutionMode; -import org.neo4j.cypher.internal.compiler.v3_0.planDescription.InternalPlanDescription; -import org.neo4j.cypher.internal.compiler.v3_0.spi.InternalResultVisitor; - -public interface GeneratedQueryExecution -{ - List javaColumns(); - - void accept( final InternalResultVisitor visitor ) throws E; - - ExecutionMode executionMode(); - - InternalPlanDescription executionPlanDescription(); - - void setSuccessfulCloseable( SuccessfulCloseable closeable ); -} diff --git a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/CypherCompiler.scala b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/CypherCompiler.scala index 94f6debcb7fdc..8ba740be19e2e 100644 --- a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/CypherCompiler.scala +++ b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/CypherCompiler.scala @@ -23,7 +23,6 @@ import java.time.Clock import org.neo4j.cypher.internal.compiler.v3_0.CompilationPhaseTracer.CompilationPhase.{AST_REWRITE, PARSING, SEMANTIC_CHECK} import org.neo4j.cypher.internal.compiler.v3_0.ast.rewriters.{normalizeReturnClauses, normalizeWithClauses} -import org.neo4j.cypher.internal.compiler.v3_0.codegen.CodeStructure import org.neo4j.cypher.internal.compiler.v3_0.executionplan._ import org.neo4j.cypher.internal.compiler.v3_0.executionplan.procs.DelegatingProcedureExecutablePlanBuilder import org.neo4j.cypher.internal.compiler.v3_0.helpers.closing @@ -72,7 +71,7 @@ case class CypherCompilerConfiguration(queryCacheSize: Int, object CypherCompilerFactory { val monitorTag = "cypher3.0" - def costBasedCompiler(graph: GraphDatabaseQueryService, config: CypherCompilerConfiguration, clock: Clock, structure: CodeStructure[GeneratedQuery], + def costBasedCompiler(graph: GraphDatabaseQueryService, config: CypherCompilerConfiguration, clock: Clock, monitors: Monitors, logger: InfoLogger, rewriterSequencer: (String) => RewriterStepSequencer, plannerName: Option[CostBasedPlannerName], @@ -86,11 +85,10 @@ object CypherCompilerFactory { val metricsFactory = CachedMetricsFactory(SimpleMetricsFactory) val queryPlanner = new DefaultQueryPlanner(LogicalPlanRewriter(rewriterSequencer)) - val compiledPlanBuilder = CompiledPlanBuilder(clock, structure) val interpretedPlanBuilder = InterpretedPlanBuilder(clock, monitors, publicTypeConverter) // Pick runtime based on input - val runtimeBuilder = RuntimeBuilder.create(runtimeName, interpretedPlanBuilder, compiledPlanBuilder, config.useErrorsOverWarnings) + val runtimeBuilder = RuntimeBuilder.create(runtimeName, interpretedPlanBuilder) val costPlanProducer = CostBasedPipeBuilderFactory.create( monitors = monitors, diff --git a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/RuntimeBuilder.scala b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/RuntimeBuilder.scala index 9304db9dc3c4b..8abb8fceb42a1 100644 --- a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/RuntimeBuilder.scala +++ b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/RuntimeBuilder.scala @@ -22,96 +22,50 @@ package org.neo4j.cypher.internal.compiler.v3_0 import java.time.Clock import org.neo4j.cypher.internal.compiler.v3_0.CompilationPhaseTracer.CompilationPhase._ -import org.neo4j.cypher.internal.compiler.v3_0.CompiledPlanBuilder.createTracer -import org.neo4j.cypher.internal.compiler.v3_0.codegen.profiling.ProfilingTracer -import org.neo4j.cypher.internal.compiler.v3_0.codegen.{CodeGenerator, CodeStructure} -import org.neo4j.cypher.internal.compiler.v3_0.executionplan.ExecutionPlanBuilder.DescriptionProvider import org.neo4j.cypher.internal.compiler.v3_0.executionplan.InterpretedExecutionPlanBuilder.interpretedToExecutionPlan -import org.neo4j.cypher.internal.compiler.v3_0.executionplan.{ExecutionPlan, GeneratedQuery, InternalExecutionResult, NewRuntimeSuccessRateMonitor, PlanFingerprint, PlanFingerprintReference, Provider, READ_ONLY} +import org.neo4j.cypher.internal.compiler.v3_0.executionplan.{ExecutionPlan, NewRuntimeSuccessRateMonitor, PlanFingerprint, PlanFingerprintReference} import org.neo4j.cypher.internal.compiler.v3_0.helpers._ -import org.neo4j.cypher.internal.compiler.v3_0.planDescription.InternalPlanDescription -import org.neo4j.cypher.internal.compiler.v3_0.planDescription.InternalPlanDescription.Arguments +import org.neo4j.cypher.internal.compiler.v3_0.planner.PeriodicCommit import org.neo4j.cypher.internal.compiler.v3_0.planner.execution.{PipeExecutionBuilderContext, PipeExecutionPlanBuilder} import org.neo4j.cypher.internal.compiler.v3_0.planner.logical.plans.LogicalPlan -import org.neo4j.cypher.internal.compiler.v3_0.planner.{CantCompileQueryException, PeriodicCommit} -import org.neo4j.cypher.internal.compiler.v3_0.spi.{GraphStatistics, PlanContext, QueryContext} -import org.neo4j.cypher.internal.frontend.v3_0.notification.{InternalNotification, RuntimeUnsupportedNotification} -import org.neo4j.cypher.internal.frontend.v3_0.{InternalException, InvalidArgumentException, SemanticTable} +import org.neo4j.cypher.internal.compiler.v3_0.spi.PlanContext +import org.neo4j.cypher.internal.frontend.v3_0.SemanticTable object RuntimeBuilder { - def create(runtimeName: Option[RuntimeName], interpretedProducer: InterpretedPlanBuilder, - compiledProducer: CompiledPlanBuilder, useErrorsOverWarnings: Boolean) = runtimeName match { - case None | Some(InterpretedRuntimeName) => InterpretedRuntimeBuilder(interpretedProducer) - case Some(CompiledRuntimeName) if useErrorsOverWarnings => ErrorReportingRuntimeBuilder(compiledProducer) - case Some(CompiledRuntimeName) => WarningFallbackRuntimeBuilder(interpretedProducer, compiledProducer) - } + + def create(runtimeName: Option[RuntimeName], interpretedProducer: InterpretedPlanBuilder) = InterpretedRuntimeBuilder( + interpretedProducer) } + trait RuntimeBuilder { - def apply(periodicCommit: Option[PeriodicCommit], logicalPlan: LogicalPlan, pipeBuildContext: PipeExecutionBuilderContext, + def apply(periodicCommit: Option[PeriodicCommit], logicalPlan: LogicalPlan, + pipeBuildContext: PipeExecutionBuilderContext, planContext: PlanContext, tracer: CompilationPhaseTracer, semanticTable: SemanticTable, monitor: NewRuntimeSuccessRateMonitor, plannerName: PlannerName, preparedQuery: PreparedQuerySemantics, createFingerprintReference: Option[PlanFingerprint] => PlanFingerprintReference, - config: CypherCompilerConfiguration): ExecutionPlan = { - try { - compiledProducer(logicalPlan, semanticTable, planContext, monitor, tracer, - plannerName, preparedQuery, createFingerprintReference) - } catch { - case e: CantCompileQueryException => - monitor.unableToHandlePlan(logicalPlan, e) - fallback(preparedQuery) - interpretedProducer - .apply(periodicCommit, logicalPlan, pipeBuildContext, planContext, tracer, preparedQuery, createFingerprintReference, config) - } - } - - def compiledProducer: CompiledPlanBuilder - - def interpretedProducer: InterpretedPlanBuilder - - def fallback(preparedQuery: PreparedQuerySemantics): Unit -} - -case class SilentFallbackRuntimeBuilder(interpretedProducer: InterpretedPlanBuilder, compiledProducer: CompiledPlanBuilder) - extends RuntimeBuilder { - - override def fallback(preparedQuery: PreparedQuerySemantics): Unit = {} -} - -case class WarningFallbackRuntimeBuilder(interpretedProducer: InterpretedPlanBuilder, compiledProducer: CompiledPlanBuilder) - extends RuntimeBuilder { - - override def fallback(preparedQuery: PreparedQuerySemantics): Unit = preparedQuery.notificationLogger - .log(RuntimeUnsupportedNotification) + config: CypherCompilerConfiguration): ExecutionPlan } case class InterpretedRuntimeBuilder(interpretedProducer: InterpretedPlanBuilder) extends RuntimeBuilder { - override def apply(periodicCommit: Option[PeriodicCommit], logicalPlan: LogicalPlan, pipeBuildContext: PipeExecutionBuilderContext, + + override def apply(periodicCommit: Option[PeriodicCommit], logicalPlan: LogicalPlan, + pipeBuildContext: PipeExecutionBuilderContext, planContext: PlanContext, tracer: CompilationPhaseTracer, semanticTable: SemanticTable, monitor: NewRuntimeSuccessRateMonitor, plannerName: PlannerName, preparedQuery: PreparedQuerySemantics, createFingerprintReference: Option[PlanFingerprint] => PlanFingerprintReference, config: CypherCompilerConfiguration): ExecutionPlan = - interpretedProducer(periodicCommit, logicalPlan, pipeBuildContext, planContext, tracer, preparedQuery, createFingerprintReference, config) - - - override def compiledProducer = throw new InternalException("This should never be called") - - override def fallback(preparedQuery: PreparedQuerySemantics) = throw new InternalException("This should never be called") -} - -case class ErrorReportingRuntimeBuilder(compiledProducer: CompiledPlanBuilder) extends RuntimeBuilder { + interpretedProducer(periodicCommit, logicalPlan, pipeBuildContext, planContext, tracer, preparedQuery, + createFingerprintReference, config) - override def interpretedProducer = throw new InternalException("This should never be called") - - override def fallback(preparedQuery: PreparedQuerySemantics) = throw new - InvalidArgumentException("The given query is not currently supported in the selected runtime") } case class InterpretedPlanBuilder(clock: Clock, monitors: Monitors, publicTypeConverter: Any => Any) { - def apply(periodicCommit: Option[PeriodicCommit], logicalPlan: LogicalPlan, pipeBuildContext: PipeExecutionBuilderContext, + def apply(periodicCommit: Option[PeriodicCommit], logicalPlan: LogicalPlan, + pipeBuildContext: PipeExecutionBuilderContext, planContext: PlanContext, tracer: CompilationPhaseTracer, preparedQuery: PreparedQuerySemantics, createFingerprintReference: Option[PlanFingerprint] => PlanFingerprintReference, config: CypherCompilerConfiguration) = @@ -121,74 +75,3 @@ case class InterpretedPlanBuilder(clock: Clock, monitors: Monitors, publicTypeCo planContext, preparedQuery, createFingerprintReference, config, publicTypeConverter) } } - -case class CompiledPlanBuilder(clock: Clock, structure:CodeStructure[GeneratedQuery]) { - - private val codeGen = new CodeGenerator(structure) - - def apply(logicalPlan: LogicalPlan, semanticTable: SemanticTable, planContext: PlanContext, - monitor: NewRuntimeSuccessRateMonitor, tracer: CompilationPhaseTracer, - plannerName: PlannerName, - preparedQuery: PreparedQuerySemantics, - createFingerprintReference:Option[PlanFingerprint]=>PlanFingerprintReference): ExecutionPlan = { - monitor.newPlanSeen(logicalPlan) - closing(tracer.beginPhase(CODE_GENERATION)) { - val compiled = codeGen.generate(logicalPlan, planContext, clock, semanticTable, plannerName) - - new ExecutionPlan { - val fingerprint = createFingerprintReference(compiled.fingerprint) - - def isStale(lastTxId: () => Long, statistics: GraphStatistics) = fingerprint.isStale(lastTxId, statistics) - - def run(queryContext: QueryContext, - executionMode: ExecutionMode, params: Map[String, Any]): InternalExecutionResult = { - val taskCloser = new TaskCloser - taskCloser.addTask(queryContext.transactionalContext.close) - try { - if (executionMode == ExplainMode) { - //close all statements - taskCloser.close(success = true) - new ExplainExecutionResult(compiled.columns.toList, - compiled.planDescription, READ_ONLY, preparedQuery.notificationLogger.notifications) - } else - compiled.executionResultBuilder(queryContext, executionMode, createTracer(executionMode), params, taskCloser) - } catch { - case (t: Throwable) => - taskCloser.close(success = false) - throw t - } - } - - def plannerUsed: PlannerName = compiled.plannerUsed - - def isPeriodicCommit: Boolean = compiled.periodicCommit.isDefined - - def runtimeUsed = CompiledRuntimeName - - override def notifications(planContext: PlanContext): Seq[InternalNotification] = Seq.empty - } - } - } -} - -object CompiledPlanBuilder { - - def createTracer( mode: ExecutionMode ) : DescriptionProvider = mode match { - case ProfileMode => - val tracer = new ProfilingTracer() - (description: InternalPlanDescription) => (new Provider[InternalPlanDescription] { - - override def get(): InternalPlanDescription = description.map { - plan: InternalPlanDescription => - val data = tracer.get(plan.id) - plan. - addArgument(Arguments.DbHits(data.dbHits())). - addArgument(Arguments.Rows(data.rows())). - addArgument(Arguments.Time(data.time())) - } - }, Some(tracer)) - case _ => (description: InternalPlanDescription) => (new Provider[InternalPlanDescription] { - override def get(): InternalPlanDescription = description - }, None) - } -} diff --git a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/RuntimeName.scala b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/RuntimeName.scala index 228204f865fc3..88f3e98b27e96 100644 --- a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/RuntimeName.scala +++ b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/RuntimeName.scala @@ -28,10 +28,6 @@ case object InterpretedRuntimeName extends RuntimeName { override val name = "INTERPRETED" } -case object CompiledRuntimeName extends RuntimeName { - override val name = "COMPILED" -} - case object ProcedureRuntimeName extends RuntimeName { override val name = "PROCEDURE" } @@ -40,9 +36,8 @@ object RuntimeName { def apply(name: String): RuntimeName = name.toUpperCase match { case InterpretedRuntimeName.name => InterpretedRuntimeName - case CompiledRuntimeName.name => CompiledRuntimeName case n => throw new IllegalArgumentException( - s"$n is not a valid runtime, valid options are ${InterpretedRuntimeName.name} and ${CompiledRuntimeName.name}") + s"$n is not a valid runtime, valid option is ${InterpretedRuntimeName.name}}") } } diff --git a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/CodeGenContext.scala b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/CodeGenContext.scala deleted file mode 100644 index 729a1104783ad..0000000000000 --- a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/CodeGenContext.scala +++ /dev/null @@ -1,65 +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.compiler.v3_0.codegen - -import org.neo4j.cypher.internal.compiler.v3_0.codegen.ir.JoinData -import org.neo4j.cypher.internal.compiler.v3_0.planDescription.Id -import org.neo4j.cypher.internal.compiler.v3_0.planner.logical.plans.LogicalPlan -import org.neo4j.cypher.internal.frontend.v3_0.symbols.CypherType -import org.neo4j.cypher.internal.frontend.v3_0.SemanticTable - -import scala.collection.mutable - -case class Variable(name: String, cypherType: CypherType, nullable: Boolean = false) - -class CodeGenContext(val semanticTable: SemanticTable, idMap: Map[LogicalPlan, Id], val namer: Namer = Namer()) { - - private val variables: mutable.Map[String, Variable] = mutable.Map() - private val probeTables: mutable.Map[CodeGenPlan, JoinData] = mutable.Map() - private val parents: mutable.Stack[CodeGenPlan] = mutable.Stack() - val operatorIds: mutable.Map[Id, String] = mutable.Map() - - def addVariable(queryVariable: String, variable: Variable) { - variables.put(queryVariable, variable) - } - - def getVariable(queryVariable: String): Variable = variables(queryVariable) - - def variableQueryVariables(): Set[String] = variables.keySet.toSet - - def addProbeTable(plan: CodeGenPlan, codeThunk: JoinData) { - probeTables.put(plan, codeThunk) - } - - def getProbeTable(plan: CodeGenPlan): JoinData = probeTables(plan) - - def pushParent(plan: CodeGenPlan) { - if (plan.isInstanceOf[LeafCodeGenPlan]) { - throw new IllegalArgumentException(s"Leafs can't be parents: $plan") - } - parents.push(plan) - } - - def popParent(): CodeGenPlan = parents.pop() - - def registerOperator(plan: LogicalPlan): String = { - operatorIds.getOrElseUpdate(idMap(plan), namer.newOpName(plan.getClass.getSimpleName)) - } -} diff --git a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/CodeGenPlan.scala b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/CodeGenPlan.scala deleted file mode 100644 index bf125bc8dd3ca..0000000000000 --- a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/CodeGenPlan.scala +++ /dev/null @@ -1,41 +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.compiler.v3_0.codegen - -import org.neo4j.cypher.internal.compiler.v3_0.codegen.ir.Instruction -import org.neo4j.cypher.internal.compiler.v3_0.planner.logical.plans.LogicalPlan - -trait CodeGenPlan { - - val logicalPlan: LogicalPlan - - def produce(context: CodeGenContext): (Option[JoinTableMethod], Seq[Instruction]) - - def consume(context: CodeGenContext, child: CodeGenPlan): (Option[JoinTableMethod], Instruction) -} - -trait LeafCodeGenPlan extends CodeGenPlan { - - override final def consume(context: CodeGenContext, child: CodeGenPlan): (Option[JoinTableMethod], Instruction) = - throw new UnsupportedOperationException("Leaf plan does not consume") -} - -case class JoinTableMethod(name: String, tableType: JoinTableType) - diff --git a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/CodeGenerator.scala b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/CodeGenerator.scala deleted file mode 100644 index 235f8ca4c7e01..0000000000000 --- a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/CodeGenerator.scala +++ /dev/null @@ -1,123 +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.compiler.v3_0.codegen - -import java.lang.Boolean.getBoolean -import java.time.Clock -import java.util - -import org.neo4j.cypher.internal.compiler.v3_0.codegen.CodeGenerator.SourceSink -import org.neo4j.cypher.internal.compiler.v3_0.codegen.ir._ -import org.neo4j.cypher.internal.compiler.v3_0.executionplan.ExecutionPlanBuilder.DescriptionProvider -import org.neo4j.cypher.internal.compiler.v3_0.executionplan.{CompiledPlan, PlanFingerprint, _} -import org.neo4j.cypher.internal.compiler.v3_0.planDescription.InternalPlanDescription.Arguments.SourceCode -import org.neo4j.cypher.internal.compiler.v3_0.planDescription.{Id, InternalPlanDescription} -import org.neo4j.cypher.internal.compiler.v3_0.planner.CantCompileQueryException -import org.neo4j.cypher.internal.compiler.v3_0.planner.logical.plans._ -import org.neo4j.cypher.internal.compiler.v3_0.planner.logical.{LogicalPlan2PlanDescription, LogicalPlanIdentificationBuilder} -import org.neo4j.cypher.internal.compiler.v3_0.spi.{InstrumentedGraphStatistics, PlanContext, QueryContext} -import org.neo4j.cypher.internal.compiler.v3_0.{ExecutionMode, PlannerName, TaskCloser} -import org.neo4j.cypher.internal.frontend.v3_0.SemanticTable -import org.neo4j.cypher.internal.frontend.v3_0.helpers.Eagerly - -class CodeGenerator(val structure: CodeStructure[GeneratedQuery]) { - - import CodeGenerator.generateCode - - type PlanDescriptionProvider = - (InternalPlanDescription) => (Provider[InternalPlanDescription], Option[QueryExecutionTracer]) - - def generate(plan: LogicalPlan, planContext: PlanContext, clock: Clock, semanticTable: SemanticTable, plannerName: PlannerName) = { - plan match { - case res: ProduceResult => - val idMap = LogicalPlanIdentificationBuilder(plan) - - var sources = Map.empty[String, String] - val sourceSink: SourceSink = if(getBoolean("org.neo4j.cypher.internal.codegen.IncludeSourcesInPlanDescription")) Some( - (className:String, sourceCode:String) => { sources = sources.updated(className, sourceCode) }) else None - - val query: GeneratedQuery = generateQuery(plan, semanticTable, idMap, res.columns, sourceSink) - - val fp = planContext.statistics match { - case igs: InstrumentedGraphStatistics => - Some(PlanFingerprint(clock.millis(), planContext.txIdProvider(), igs.snapshot.freeze)) - case _ => - None - } - - val description: InternalPlanDescription = sources.foldLeft(LogicalPlan2PlanDescription(plan, idMap)) { - case (root, (className, sourceCode)) => root.addArgument(SourceCode(className, sourceCode)) - } - - val builder = new RunnablePlan { - def apply(queryContext: QueryContext, execMode: ExecutionMode, - descriptionProvider: DescriptionProvider, params: Map[String, Any], - closer: TaskCloser): InternalExecutionResult = { - val (provider, tracer) = descriptionProvider(description) - val execution: GeneratedQueryExecution = query.execute(closer, queryContext, execMode, - provider, tracer.getOrElse(QueryExecutionTracer.NONE), asJavaHashMap(params)) - new CompiledExecutionResult(closer, queryContext, execution, provider) - } - } - - CompiledPlan(updating = false, None, fp, plannerName, description, res.columns, builder) - - case _ => throw new CantCompileQueryException("Can only compile plans with ProduceResult on top") - } - } - - private def generateQuery(plan: LogicalPlan, semantics: SemanticTable, ids: Map[LogicalPlan, Id], columns: Seq[String], sources: SourceSink = None): GeneratedQuery = { - import LogicalPlanConverter._ - implicit val context = new CodeGenContext(semantics, ids) - val (_, instructions) = asCodeGenPlan(plan).produce(context) - generateCode(structure)(instructions, context.operatorIds.map { - case (id: Id, field: String) => field -> id - }.toMap, columns, sources) - } - - private def asJavaHashMap(params: scala.collection.Map[String, Any]) = { - val jMap = new util.HashMap[String, Object]() - params.foreach { - case (key, value) => jMap.put(key, javaValue(value)) - } - jMap - } - - import scala.collection.JavaConverters._ - private def javaValue(value: Any): Object = value match { - case null => null - case iter: Seq[_] => iter.map(javaValue).asJava - case iter: scala.collection.Map[_, _] => Eagerly.immutableMapValues(iter, javaValue).asJava - case x: Any => x.asInstanceOf[AnyRef] - } -} - -object CodeGenerator { - type SourceSink = Option[(String, String) => Unit] - - def generateCode[T](structure: CodeStructure[T])(instructions: Seq[Instruction], operatorIds: Map[String, Id], columns: Seq[String], sources:SourceSink=None)(implicit context: CodeGenContext): T = { - structure.generateQuery(packageName, Namer.newClassName(), columns, operatorIds, sources) { accept => - instructions.foreach(insn => insn.init(accept)) - instructions.foreach(insn => insn.body(accept)) - } - } - - private val packageName = "org.neo4j.cypher.internal.compiler.v3_0.generated" -} diff --git a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/CodeStructure.scala b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/CodeStructure.scala deleted file mode 100644 index 65a60507f59e5..0000000000000 --- a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/CodeStructure.scala +++ /dev/null @@ -1,146 +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.compiler.v3_0.codegen - -import org.neo4j.cypher.internal.compiler.v3_0.planDescription.Id -import org.neo4j.cypher.internal.frontend.v3_0.SemanticDirection -import org.neo4j.cypher.internal.frontend.v3_0.symbols.CypherType - -/** - * This constitutes the SPI for code generation. - */ -trait CodeStructure[T] { - type SourceSink = (String, String) => Unit - def generateQuery(packageName: String, className: String, columns: Seq[String], operatorIds: Map[String, Id], sourceSink: Option[SourceSink]) - (block: MethodStructure[_] => Unit)(implicit codeGenContext: CodeGenContext): T -} - -sealed trait JoinTableType -sealed trait CountingJoinTableType extends JoinTableType -sealed trait RecordingJoinTableType extends JoinTableType - -case object LongToCountTable extends CountingJoinTableType -case object LongsToCountTable extends CountingJoinTableType -case class LongToListTable(structure: Map[String, CypherType], localMap: Map[String, String]) extends RecordingJoinTableType -case class LongsToListTable(structure: Map[String, CypherType], localMap: Map[String, String]) extends RecordingJoinTableType - -trait MethodStructure[E] { - - - // misc - def projectVariable(variableName: String, value: E) - def declareFlag(name: String, initialValue: Boolean) - def updateFlag(name: String, newValue: Boolean) - def declarePredicate(name: String): Unit - def declare(varName: String, cypherType: CypherType): Unit - def declareProperty(name: String): Unit - def declareCounter(name: String, initialValue: E): Unit - def putField(structure: Map[String, CypherType], value: E, fieldType: CypherType, fieldName: String, localVar: String): Unit - def updateProbeTable(structure: Map[String, CypherType], tableVar: String, tableType: RecordingJoinTableType, keyVars: Seq[String], element: E): Unit - def probe(tableVar: String, tableType: JoinTableType, keyVars: Seq[String])(block: MethodStructure[E]=>Unit): Unit - def updateProbeTableCount(tableVar: String, tableType: CountingJoinTableType, keyVar: Seq[String]): Unit - def allocateProbeTable(tableVar: String, tableType: JoinTableType): Unit - def method(resultType: JoinTableType, resultVar: String, methodName: String)(block: MethodStructure[E]=>Unit): Unit - def coerceToBoolean(propertyExpression: E): E - - // expressions - def decreaseCounterAndCheckForZero(name: String): E - def counterEqualsZero(variableName: String): E - def newTableValue(targetVar: String, structure: Map[String, CypherType]): E - def constant(value: Object): E - def asMap(map: Map[String, E]): E - def asList(values: Seq[E]): E - - def toSet(value: E): E - - def castToCollection(value: E): E - - def load(varName: String): E - - // arithmetic - def add(lhs: E, rhs: E): E - def sub(lhs: E, rhs: E): E - def mul(lhs: E, rhs: E): E - def div(lhs: E, rhs: E): E - def mod(lhs: E, rhs: E): E - - // predicates - def threeValuedNot(value: E): E - def not(value: E): E - def threeValuedEquals(lhs: E, rhs: E): E - def eq(lhs: E, rhs: E): E - def or(lhs: E, rhs: E): E - def threeValuedOr(lhs: E, rhs: E): E - - // null handling - def markAsNull(varName: String, cypherType: CypherType): Unit - def nullable(varName: String, cypherType: CypherType, onSuccess: E): E - def notNull(name: String, cypherType: CypherType): E - - // parameters - def expectParameter(key: String, variableName: String): Unit - - // tracing - def trace[V](planStepId: String)(block: MethodStructure[E] => V): V - def incrementDbHits(): Unit - def incrementRows(): Unit - - // db access - def labelScan(iterVar: String, labelIdVar: String): Unit - def hasLabel(nodeVar: String, labelVar: String, predVar: String): E - def allNodesScan(iterVar: String): Unit - def lookupLabelId(labelIdVar: String, labelName: String): Unit - def lookupRelationshipTypeId(typeIdVar: String, typeName: String): Unit - def nodeGetAllRelationships(iterVar: String, nodeVar: String, direction: SemanticDirection): Unit - def nodeGetRelationships(iterVar: String, nodeVar: String, direction: SemanticDirection, typeVars: Seq[String]): Unit - def connectingRelationships(iterVar: String, fromNode: String, dir: SemanticDirection, toNode:String) - def connectingRelationships(iterVar: String, fromNode: String, dir: SemanticDirection, types: Seq[String], toNode: String) - def nextNode(targetVar: String, iterVar: String): Unit - def nextRelationshipAndNode(toNodeVar: String, iterVar: String, direction: SemanticDirection, fromNodeVar: String, relVar: String): Unit - def nextRelationship(iterVar: String, direction: SemanticDirection, relVar: String): Unit - def hasNext(iterVar: String): E - def nodeGetPropertyById(nodeIdVar: String, propId: Int, propValueVar: String): Unit - def nodeGetPropertyForVar(nodeIdVar: String, propIdVar: String, propValueVar: String): Unit - def relationshipGetPropertyById(nodeIdVar: String, propId: Int, propValueVar: String): Unit - def relationshipGetPropertyForVar(nodeIdVar: String, propIdVar: String, propValueVar: String): Unit - def lookupPropertyKey(propName: String, propVar: String) - def indexSeek(iterVar: String, descriptorVar: String, value: E): Unit - def indexUniqueSeek(name: String, descriptorVar: String, value: E) - def relType(relIdVar: String, typeVar: String): Unit - def newIndexDescriptor(descriptorVar: String, labelVar: String, propKeyVar: String): Unit - def createRelExtractor(extractorName: String): Unit - - - // code structure - def whileLoop(test: E)(block: MethodStructure[E] => Unit): Unit - def forEach(varName: String, cypherType: CypherType, iterable: E)(block: MethodStructure[E] => Unit): Unit - def ifStatement(test: E)(block: MethodStructure[E] => Unit): Unit - def ternaryOperator(test:E, onSuccess:E, onError: E): E - def returnSuccessfully(): Unit - - // results - def materializeNode(nodeIdVar: String): E - def node(nodeIdVar: String): E - def materializeRelationship(relIdVar: String): E - def relationship(relIdVar: String): E - /** Feed single row to the given visitor */ - def visitorAccept(): Unit - def setInRow(column: String, value: E): Unit -} diff --git a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/LogicalPlanConverter.scala b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/LogicalPlanConverter.scala deleted file mode 100644 index d2ce9c69784e8..0000000000000 --- a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/LogicalPlanConverter.scala +++ /dev/null @@ -1,443 +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.compiler.v3_0.codegen - -import org.neo4j.cypher.internal.compiler.v3_0.codegen.ir._ -import org.neo4j.cypher.internal.compiler.v3_0.codegen.ir.expressions._ -import org.neo4j.cypher.internal.compiler.v3_0.commands.{ManyQueryExpression, QueryExpression, RangeQueryExpression, SingleQueryExpression} -import org.neo4j.cypher.internal.compiler.v3_0.planner.CantCompileQueryException -import org.neo4j.cypher.internal.compiler.v3_0.planner.logical.plans -import org.neo4j.cypher.internal.compiler.v3_0.planner.logical.plans._ -import org.neo4j.cypher.internal.frontend.v3_0.ast.Expression -import org.neo4j.cypher.internal.frontend.v3_0.helpers.Eagerly -import org.neo4j.cypher.internal.frontend.v3_0.{InternalException, ast, symbols} - -object LogicalPlanConverter { - - def asCodeGenPlan(logicalPlan: LogicalPlan): CodeGenPlan = logicalPlan match { - case p: SingleRow => singleRowAsCodeGenPlan(p) - case p: AllNodesScan => allNodesScanAsCodeGenPlan(p) - case p: NodeByLabelScan => nodeByLabelScanAsCodeGenPlan(p) - case p: NodeIndexSeek => nodeIndexSeekAsCodeGenPlan(p) - case p: NodeUniqueIndexSeek => nodeUniqueIndexSeekAsCodeGen(p) - case p: Expand => expandAsCodeGenPlan(p) - case p: OptionalExpand => optExpandAsCodeGenPlan(p) - case p: NodeHashJoin => nodeHashJoinAsCodeGenPlan(p) - case p: CartesianProduct => cartesianProductAsCodeGenPlan(p) - case p: Selection => selectionAsCodeGenPlan(p) - case p: plans.Limit => limitAsCodeGenPlan(p) - case p: ProduceResult => produceResultsAsCodeGenPlan(p) - case p: plans.Projection => projectionAsCodeGenPlan(p) - - case _ => - throw new CantCompileQueryException(s"$logicalPlan is not yet supported") - } - - private def singleRowAsCodeGenPlan(singleRow: SingleRow) = new CodeGenPlan with LeafCodeGenPlan { - override def produce(context: CodeGenContext): (Option[JoinTableMethod], Seq[Instruction]) = { - val (methodHandle, actions) = context.popParent().consume(context, this) - (methodHandle, Seq(actions)) - } - - override val logicalPlan: LogicalPlan = singleRow - } - - private def projectionAsCodeGenPlan(projection: plans.Projection) = new CodeGenPlan { - - override val logicalPlan = projection - - override def produce(context: CodeGenContext) = { - context.pushParent(this) - asCodeGenPlan(projection.lhs.get).produce(context) - } - - override def consume(context: CodeGenContext, child: CodeGenPlan) = { - val projectionOpName = context.registerOperator(projection) - val columns = Eagerly.immutableMapValues(projection.expressions, - (e: ast.Expression) => ExpressionConverter.createProjection(e)(context)) - val vars = columns.map { - case (name, expr) => - val variable = Variable(context.namer.newVarName(), expr.cypherType(context), expr.nullable(context)) - context.addVariable(name, variable) - variable -> expr - } - val (methodHandle, action) = context.popParent().consume(context, this) - (methodHandle, ir.Projection(projectionOpName, vars, action)) - } - } - - private def produceResultsAsCodeGenPlan(produceResults: ProduceResult) = new CodeGenPlan { - - override val logicalPlan = produceResults - - override def produce(context: CodeGenContext) = { - context.pushParent(this) - asCodeGenPlan(produceResults.lhs.get).produce(context) - } - - override def consume(context: CodeGenContext, child: CodeGenPlan) = { - val produceResultOpName = context.registerOperator(produceResults) - val projections = (produceResults.lhs.get match { - // if lhs is projection than we can simply load things that it projected - case _: plans.Projection => produceResults.columns.map(c => c -> LoadVariable(context.getVariable(c))) - // else we have to evaluate all expressions ourselves - case _ => produceResults.columns.map(c => c -> ExpressionConverter.createExpressionForVariable(c)(context)) - }).toMap - - (None, AcceptVisitor(produceResultOpName, projections)) - } - } - - private def allNodesScanAsCodeGenPlan(allNodesScan: AllNodesScan) = new CodeGenPlan with LeafCodeGenPlan { - override val logicalPlan: LogicalPlan = allNodesScan - - override def produce(context: CodeGenContext): (Option[JoinTableMethod], Seq[Instruction]) = { - val variable = Variable(context.namer.newVarName(), symbols.CTNode) - context.addVariable(allNodesScan.idName.name, variable) - val (methodHandle, actions) = context.popParent().consume(context, this) - val opName = context.registerOperator(logicalPlan) - (methodHandle, Seq(WhileLoop(variable, ScanAllNodes(opName), actions))) - } - } - - private def nodeByLabelScanAsCodeGenPlan(nodeByLabelScan: NodeByLabelScan) = new CodeGenPlan with LeafCodeGenPlan { - override val logicalPlan: LogicalPlan = nodeByLabelScan - - override def produce(context: CodeGenContext): (Option[JoinTableMethod], Seq[Instruction]) = { - val nodeVar = Variable(context.namer.newVarName(), symbols.CTNode) - val labelVar = context.namer.newVarName() - context.addVariable(nodeByLabelScan.idName.name, nodeVar) - val (methodHandle, actions) = context.popParent().consume(context, this) - val opName = context.registerOperator(logicalPlan) - (methodHandle, Seq(WhileLoop(nodeVar, ScanForLabel(opName, nodeByLabelScan.label.name, labelVar), actions))) - } - } - - private type IndexSeekFun = (String, String, CodeGenExpression, Variable, Instruction) => Instruction - - // Used by both nodeIndexSeekAsCodeGenPlan and nodeUniqueIndexSeekAsCodeGenPlan - private def sharedIndexSeekAsCodeGenPlan(indexSeekFun: IndexSeekFun)(idName: String, valueExpr: QueryExpression[Expression], indexSeek: LogicalPlan) = - new CodeGenPlan with LeafCodeGenPlan { - override val logicalPlan: LogicalPlan = indexSeek - - override def produce(context: CodeGenContext): (Option[JoinTableMethod], Seq[Instruction]) = { - val nodeVar = Variable(context.namer.newVarName(), symbols.CTNode) - context.addVariable(idName, nodeVar) - - val (methodHandle, actions) = context.popParent().consume(context, this) - val opName = context.registerOperator(logicalPlan) - val indexSeekInstruction = valueExpr match { - //single expression, do a index lookup for that value - case SingleQueryExpression(e) => - val expression = ExpressionConverter.createExpression(e)(context) - indexSeekFun(opName, context.namer.newVarName(), expression, nodeVar, actions) - //collection, create set and for each element of the set do an index lookup - case ManyQueryExpression(e: ast.Collection) => - val expression = ToSet(ExpressionConverter.createExpression(e)(context)) - val expressionVar = Variable(context.namer.newVarName(), symbols.CTAny, nullable = false) - - ForEachExpression(expressionVar, expression, - indexSeekFun(opName, context.namer.newVarName(), LoadVariable(expressionVar), nodeVar, actions)) - //Unknown, try to cast to collection and then same as above - case ManyQueryExpression(e) => - val expression = ToSet(CastToCollection(ExpressionConverter.createExpression(e)(context))) - val expressionVar = Variable(context.namer.newVarName(), symbols.CTAny, nullable = false) - ForEachExpression(expressionVar, expression, - indexSeekFun(opName, context.namer.newVarName(), LoadVariable(expressionVar), nodeVar, actions)) - - case e: RangeQueryExpression[_] => - throw new CantCompileQueryException(s"To be done") - - case e => throw new InternalException(s"$e is not a valid QueryExpression") - } - - (methodHandle, Seq(indexSeekInstruction)) - } - } - - private def nodeIndexSeekAsCodeGenPlan(indexSeek: NodeIndexSeek) = { - def indexSeekFun(opName: String, descriptorVar: String, expression: CodeGenExpression, - nodeVar: Variable, actions: Instruction) = - WhileLoop(nodeVar, IndexSeek(opName, indexSeek.label.name, indexSeek.propertyKey.name, - descriptorVar, expression), actions) - - sharedIndexSeekAsCodeGenPlan(indexSeekFun)(indexSeek.idName.name, indexSeek.valueExpr, indexSeek) - } - - private def nodeUniqueIndexSeekAsCodeGen(indexSeek: NodeUniqueIndexSeek) = { - def indexSeekFun(opName: String, descriptorVar: String, expression: CodeGenExpression, - nodeVar: Variable, actions: Instruction) = - IndexUniqueSeek(opName, indexSeek.label.name, indexSeek.propertyKey.name, - descriptorVar, expression, nodeVar, actions) - - sharedIndexSeekAsCodeGenPlan(indexSeekFun)(indexSeek.idName.name, indexSeek.valueExpr, indexSeek) - } - - private def nodeHashJoinAsCodeGenPlan(nodeHashJoin: NodeHashJoin) = new CodeGenPlan { - - override val logicalPlan: LogicalPlan = nodeHashJoin - - override def produce(context: CodeGenContext): (Option[JoinTableMethod], Seq[Instruction]) = { - context.pushParent(this) - val (Some(symbol), leftInstructions) = asCodeGenPlan(logicalPlan.lhs.get).produce(context) - val opName = context.registerOperator(logicalPlan) - val lhsMethod = MethodInvocation(Set(opName), symbol, context.namer.newMethodName(), leftInstructions) - - context.pushParent(this) - val (otherSymbol, rightInstructions) = asCodeGenPlan(logicalPlan.rhs.get).produce(context) - (otherSymbol, lhsMethod +: rightInstructions) - } - - override def consume(context: CodeGenContext, child: CodeGenPlan): (Option[JoinTableMethod], Instruction) = { - if (child.logicalPlan eq logicalPlan.lhs.get) { - val joinNodes = nodeHashJoin.nodes.map(n => context.getVariable(n.name)) - val probeTableName = context.namer.newVarName() - - val lhsSymbols = nodeHashJoin.left.availableSymbols.map(_.name) - val nodeNames = nodeHashJoin.nodes.map(_.name) - val notNodeSymbols = lhsSymbols intersect context.variableQueryVariables() diff nodeNames - val symbols = notNodeSymbols.map(s => s -> context.getVariable(s)).toMap - - - val opName = context.registerOperator(nodeHashJoin) - val probeTable = BuildProbeTable(opName, probeTableName, joinNodes, symbols)(context) - val probeTableSymbol = JoinTableMethod(probeTableName, probeTable.tableType) - - context.addProbeTable(this, probeTable.joinData) - - - (Some(probeTableSymbol), probeTable) - - } - else if (child.logicalPlan eq logicalPlan.rhs.get) { - - val joinNodes = nodeHashJoin.nodes.map(n => context.getVariable(n.name)) - val joinData = context.getProbeTable(this) - joinData.vars foreach { case (_, symbol) => context.addVariable(symbol.variable, symbol.outgoing) } - - val (methodHandle, actions) = context.popParent().consume(context, this) - - (methodHandle, GetMatchesFromProbeTable(joinNodes, joinData, actions)) - } - else { - throw new InternalException(s"Unexpected consume call by $child") - } - } - } - - private def expandAsCodeGenPlan(expand: Expand) = new CodeGenPlan with SingleChildPlan { - - override val logicalPlan: LogicalPlan = expand - - override def consume(context: CodeGenContext, child: CodeGenPlan): (Option[JoinTableMethod], Instruction) = expand - .mode match { - case ExpandAll => expandAllConsume(context, child) - case ExpandInto => expandIntoConsume(context, child) - } - - private def expandAllConsume(context: CodeGenContext, - child: CodeGenPlan): (Option[JoinTableMethod], Instruction) = { - val relVar = Variable(context.namer.newVarName(), symbols.CTRelationship) - val toNodeVar = Variable(context.namer.newVarName(), symbols.CTNode) - context.addVariable(expand.relName.name, relVar) - context.addVariable(expand.to.name, toNodeVar) - - val (methodHandle, action) = context.popParent().consume(context, this) - val fromNodeVar = context.getVariable(expand.from.name) - val typeVar2TypeName = expand.types.map(t => context.namer.newVarName() -> t.name).toMap - val opName = context.registerOperator(expand) - val expandGenerator = ExpandAllLoopDataGenerator(opName, fromNodeVar, expand.dir, typeVar2TypeName, toNodeVar, relVar) - - (methodHandle, WhileLoop(relVar, expandGenerator, action)) - } - - private def expandIntoConsume(context: CodeGenContext, - child: CodeGenPlan): (Option[JoinTableMethod], Instruction) = { - val relVar = Variable(context.namer.newVarName(), symbols.CTRelationship) - context.addVariable(expand.relName.name, relVar) - - val (methodHandle, action) = context.popParent().consume(context, this) - val fromNodeVar = context.getVariable(expand.from.name) - val toNodeVar = context.getVariable(expand.to.name) - val typeVar2TypeName = expand.types.map(t => context.namer.newVarName() -> t.name).toMap - val opName = context.registerOperator(expand) - val expandGenerator = ExpandIntoLoopDataGenerator(opName, fromNodeVar, expand.dir, typeVar2TypeName, toNodeVar, relVar) - - (methodHandle, WhileLoop(relVar, expandGenerator, action)) - } - } - - private def optExpandAsCodeGenPlan(optionalExpand: OptionalExpand) = new CodeGenPlan { - - override val logicalPlan: LogicalPlan = optionalExpand - - override def produce(context: CodeGenContext): (Option[JoinTableMethod], Seq[Instruction]) = { - context.pushParent(this) - asCodeGenPlan(optionalExpand.lhs.get).produce(context) - } - - override def consume(context: CodeGenContext, - child: CodeGenPlan): (Option[JoinTableMethod], Instruction) = optionalExpand.mode match { - case ExpandAll => expandAllConsume(context, child) - case ExpandInto => expandIntoConsume(context, child) - } - - private def expandAllConsume(context: CodeGenContext, - child: CodeGenPlan): (Option[JoinTableMethod], Instruction) = { - //mark relationship and node to visit as nullable - val relVar = Variable(context.namer.newVarName(), symbols.CTRelationship, nullable = true) - val toNodeVar = Variable(context.namer.newVarName(), symbols.CTNode, nullable = true) - context.addVariable(optionalExpand.relName.name, relVar) - context.addVariable(optionalExpand.to.name, toNodeVar) - - val (methodHandle, action) = context.popParent().consume(context, this) - val fromNodeVar = context.getVariable(optionalExpand.from.name) - val typeVar2TypeName = optionalExpand.types.map(t => context.namer.newVarName() -> t.name).toMap - val opName = context.registerOperator(optionalExpand) - - //name of flag to check if results were yielded - val yieldFlag = context.namer.newVarName() - - val predicatesAsCodeGenExpressions = - optionalExpand. - predicates. - // We reverse the order of the predicates so the least selective comes first in line - reverseMap(ExpressionConverter.createPredicate(_)(context)) - - //wrap inner instructions with predicates - - // the least selective predicate gets wrapped in an If, which is then wrapped in an If, until we reach the action - val instructionWithPredicates = predicatesAsCodeGenExpressions.foldLeft[Instruction]( - CheckingInstruction(action, yieldFlag)) { - case (acc, predicate) => If(predicate, acc) - } - - val expand = ExpandAllLoopDataGenerator(opName, fromNodeVar, optionalExpand.dir, typeVar2TypeName, toNodeVar, relVar) - - val loop = WhileLoop(relVar, expand, instructionWithPredicates) - - (methodHandle, NullingInstruction(loop, yieldFlag, action, relVar, toNodeVar)) - } - - private def expandIntoConsume(context: CodeGenContext, - child: CodeGenPlan): (Option[JoinTableMethod], Instruction) = { - //mark relationship to visit as nullable - val relVar = Variable(context.namer.newVarName(), symbols.CTRelationship, nullable = true) - context.addVariable(optionalExpand.relName.name, relVar) - - val (methodHandle, action) = context.popParent().consume(context, this) - val fromNodeVar = context.getVariable(optionalExpand.from.name) - val toNodeVar = context.getVariable(optionalExpand.to.name) - val typeVar2TypeName = optionalExpand.types.map(t => context.namer.newVarName() -> t.name).toMap - val opName = context.registerOperator(optionalExpand) - - //name of flag to check if results were yielded - val yieldFlag = context.namer.newVarName() - - val predicatesAsCodeGenExpressions = - optionalExpand. - predicates. - // We reverse the order of the predicates so the least selective comes first in line - reverseMap(ExpressionConverter.createPredicate(_)(context)) - - //wrap inner instructions with predicates - - // the least selective predicate gets wrapped in an If, which is then wrapped in an If, until we reach the action - val instructionWithPredicates = predicatesAsCodeGenExpressions.foldLeft[Instruction]( - CheckingInstruction(action, yieldFlag)) { - case (acc, predicate) => If(predicate, acc) - } - - val expand = ExpandIntoLoopDataGenerator(opName, fromNodeVar, optionalExpand.dir, typeVar2TypeName, toNodeVar, relVar) - - val loop = WhileLoop(relVar, expand, instructionWithPredicates) - - (methodHandle, NullingInstruction(loop, yieldFlag, action, relVar)) - } - } - - private def cartesianProductAsCodeGenPlan(cartesianProduct: CartesianProduct) = new CodeGenPlan { - - override val logicalPlan: LogicalPlan = cartesianProduct - - override def produce(context: CodeGenContext): (Option[JoinTableMethod], Seq[Instruction]) = { - context.pushParent(this) - asCodeGenPlan(cartesianProduct.lhs.get).produce(context) - } - - override def consume(context: CodeGenContext, child: CodeGenPlan): (Option[JoinTableMethod], Instruction) = { - if (child.logicalPlan eq cartesianProduct.lhs.get) { - context.pushParent(this) - val (m, actions) = asCodeGenPlan(cartesianProduct.rhs.get).produce(context) - (m, actions.headOption.getOrElse(throw new InternalException("Illegal call chain"))) - } else if (child.logicalPlan eq cartesianProduct.rhs.get) { - val opName = context.registerOperator(cartesianProduct) - val (m, instruction) = context.popParent().consume(context, this) - (m, CartesianProductInstruction(opName, instruction)) - } - else { - throw new InternalException(s"Unexpected consume call by $child") - } - } - } - - private def selectionAsCodeGenPlan(selection: Selection) = new CodeGenPlan with SingleChildPlan { - - override val logicalPlan: LogicalPlan = selection - - override def consume(context: CodeGenContext, child: CodeGenPlan): (Option[JoinTableMethod], Instruction) = { - val opName = context.registerOperator(selection) - val predicates = selection.predicates.map( - ExpressionConverter.createPredicate(_)(context) - ) - - val (methodHandle, innerBlock) = context.popParent().consume(context, this) - - val instruction = predicates.reverse.foldLeft[Instruction](innerBlock) { - case (acc, predicate) => If(predicate, acc) - } - - (methodHandle, SelectionInstruction(opName, instruction)) - } - } - - private def limitAsCodeGenPlan(limit: plans.Limit) = new CodeGenPlan with SingleChildPlan { - - override val logicalPlan: LogicalPlan = limit - - override def consume(context: CodeGenContext, child: CodeGenPlan): (Option[JoinTableMethod], Instruction) = { - val opName = context.registerOperator(limit) - val count = ExpressionConverter.createExpression(limit.count)(context) - val counterName = context.namer.newVarName() - - val (methodHandle, innerBlock) = context.popParent().consume(context, this) - val instruction = DecreaseAndReturnWhenZero(opName, counterName, innerBlock, count) - - (methodHandle, instruction) - } - } - - trait SingleChildPlan extends CodeGenPlan { - - final override def produce(context: CodeGenContext): (Option[JoinTableMethod], Seq[Instruction]) = { - context.pushParent(this) - asCodeGenPlan(logicalPlan.lhs.get).produce(context) - } - } - -} diff --git a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/Namer.scala b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/Namer.scala deleted file mode 100644 index 4246a2af0bc9f..0000000000000 --- a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/Namer.scala +++ /dev/null @@ -1,55 +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.compiler.v3_0.codegen - -import java.util.concurrent.atomic.AtomicInteger - -class Namer(classNameCounter: AtomicInteger, varPrefix: String = "v", methodPrefix: String = "m", operationPrefix: String = "OP") { - - private var methodNameCounter = 0 - private var varNameCounter = 0 - private var opNameCounter = 0 - - def newMethodName(): String = { - methodNameCounter += 1 - s"$methodPrefix$methodNameCounter" - } - - def newVarName(): String = { - varNameCounter += 1 - s"$varPrefix$varNameCounter" - } - - def newOpName(planName: String): String = { - opNameCounter += 1 - s"$operationPrefix${opNameCounter}_$planName" - } -} - -object Namer { - - private val classNameCounter = new AtomicInteger() - - def apply(): Namer = new Namer(classNameCounter) - - def newClassName() = { - s"GeneratedExecutionPlan${classNameCounter.incrementAndGet()}" - } -} diff --git a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/QueryExecutionEvent.java b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/QueryExecutionEvent.java deleted file mode 100644 index 51430e9c10b4d..0000000000000 --- a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/QueryExecutionEvent.java +++ /dev/null @@ -1,48 +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.compiler.v3_0.codegen; - -public interface QueryExecutionEvent extends AutoCloseable -{ - void dbHit(); - - void row(); - - @Override - void close(); - - QueryExecutionEvent NONE = new QueryExecutionEvent() - { - @Override - public void dbHit() - { - } - - @Override - public void row() - { - } - - @Override - public void close() - { - } - }; -} diff --git a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/AcceptVisitor.scala b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/AcceptVisitor.scala deleted file mode 100644 index ae771c020b19a..0000000000000 --- a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/AcceptVisitor.scala +++ /dev/null @@ -1,46 +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.compiler.v3_0.codegen.ir - -import org.neo4j.cypher.internal.compiler.v3_0.codegen.ir.expressions.CodeGenExpression -import org.neo4j.cypher.internal.compiler.v3_0.codegen.{CodeGenContext, MethodStructure} - -case class AcceptVisitor(produceResultOpName: String, columns: Map[String, CodeGenExpression]) - extends Instruction { - - override def body[E](generator: MethodStructure[E])(implicit context: CodeGenContext) = { - generator.trace(produceResultOpName) { body => - body.incrementRows() - columns.foreach { case (k, v) => - body.setInRow(k, v.generateExpression(body)) - } - body.visitorAccept() - } - } - - override protected def operatorId = Set(produceResultOpName) - - override protected def children = Seq.empty - - override def init[E](generator: MethodStructure[E])(implicit context: CodeGenContext) { - columns.values.foreach(_.init(generator)) - super.init(generator) - } -} diff --git a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/BuildProbeTable.scala b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/BuildProbeTable.scala deleted file mode 100644 index 24d4ad82dc301..0000000000000 --- a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/BuildProbeTable.scala +++ /dev/null @@ -1,89 +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.compiler.v3_0.codegen.ir - -import org.neo4j.cypher.internal.compiler.v3_0.codegen._ - -sealed trait BuildProbeTable extends Instruction { - - override def init[E](generator: MethodStructure[E])(implicit context: CodeGenContext) = - generator.allocateProbeTable(name, tableType) - - protected val name: String - - def joinData: JoinData - def tableType: JoinTableType - - override protected def children = Seq.empty -} - -object BuildProbeTable { - - def apply(id: String, name: String, nodes: Set[Variable], valueSymbols: Map[String, Variable])(implicit context: CodeGenContext): BuildProbeTable = { - if (valueSymbols.isEmpty) BuildCountingProbeTable(id, name, nodes) - else BuildRecordingProbeTable(id, name, nodes, valueSymbols) - } -} - -case class BuildRecordingProbeTable(id:String, name: String, nodes: Set[Variable], valueSymbols: Map[String, Variable]) - (implicit context: CodeGenContext) - extends BuildProbeTable { - - override def body[E](generator: MethodStructure[E])(implicit ignored: CodeGenContext): Unit = { - val value = generator.newTableValue(context.namer.newVarName(), valueStructure) - fieldToVarName.foreach { - case (fieldName, localName) => generator.putField(valueStructure, value, localName.incoming.cypherType, fieldName, localName.incoming.name) - } - generator.updateProbeTable(valueStructure, name, tableType, nodes.toSeq.map(_.name), value) - } - - override protected def operatorId = Set(id) - - private val fieldToVarName = valueSymbols.map { - case (variable, incoming) => (context.namer.newVarName(), VariableData(variable, incoming, incoming.copy(name = context.namer.newVarName()))) - } - - private val varNameToField = fieldToVarName.map { - case (fieldName, localName) => localName.outgoing.name -> fieldName - } - - private val valueStructure = fieldToVarName.mapValues(_.outgoing.cypherType) - - override val tableType = if(nodes.size == 1 ) LongToListTable(valueStructure, varNameToField) - else LongsToListTable(valueStructure, varNameToField) - - val joinData: JoinData = JoinData(fieldToVarName, name, tableType, id) -} - -case class BuildCountingProbeTable(id: String, name: String, nodes: Set[Variable]) extends BuildProbeTable { - - override def body[E](generator: MethodStructure[E])(implicit context: CodeGenContext) = - generator.updateProbeTableCount(name, tableType, nodes.toSeq.map(_.name)) - - override protected def operatorId = Set(id) - - override val tableType = if (nodes.size == 1) LongToCountTable else LongsToCountTable - - override def joinData = { - JoinData(Map.empty, name, tableType, id) - } -} -case class VariableData(variable: String, incoming: Variable, outgoing: Variable) -case class JoinData(vars: Map[String, VariableData], tableVar: String, tableType: JoinTableType, id: String) diff --git a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/CartesianProductInstruction.scala b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/CartesianProductInstruction.scala deleted file mode 100644 index 7453ebb0b1b7f..0000000000000 --- a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/CartesianProductInstruction.scala +++ /dev/null @@ -1,37 +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.compiler.v3_0.codegen.ir - -import org.neo4j.cypher.internal.compiler.v3_0.codegen.{CodeGenContext, MethodStructure} - -case class CartesianProductInstruction(id: String, instruction: Instruction) extends Instruction { - - override def init[E](generator: MethodStructure[E])(implicit context: CodeGenContext) = super.init(generator) - - override def body[E](generator: MethodStructure[E])(implicit context: CodeGenContext) = - generator.trace(id) { body => - body.incrementRows() - instruction.body(body) - } - - override def children = Seq(instruction) - - override protected def operatorId = Set(id) -} diff --git a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/CheckingInstruction.scala b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/CheckingInstruction.scala deleted file mode 100644 index e2a8c67cf9037..0000000000000 --- a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/CheckingInstruction.scala +++ /dev/null @@ -1,40 +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.compiler.v3_0.codegen.ir - -import org.neo4j.cypher.internal.compiler.v3_0.codegen.{CodeGenContext, MethodStructure} - -/** - * Generates instruction for for updating a provided flag before creating the inner instruction - */ -case class CheckingInstruction(inner: Instruction, yieldedFlagVar: String) - extends Instruction { - - override def init[E](generator: MethodStructure[E])(implicit context: CodeGenContext) = { - inner.init(generator) - } - - override def body[E](generator: MethodStructure[E])(implicit context: CodeGenContext) = { - generator.updateFlag(yieldedFlagVar, newValue = true) - inner.body(generator) - } - - override def children = Seq(inner) -} diff --git a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/DecreaseAndReturnWhenZero.scala b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/DecreaseAndReturnWhenZero.scala deleted file mode 100644 index bc8c5e946554d..0000000000000 --- a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/DecreaseAndReturnWhenZero.scala +++ /dev/null @@ -1,52 +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.compiler.v3_0.codegen.ir - -import org.neo4j.cypher.internal.compiler.v3_0.codegen.ir.expressions.CodeGenExpression -import org.neo4j.cypher.internal.compiler.v3_0.codegen.{CodeGenContext, MethodStructure} - -case class DecreaseAndReturnWhenZero(opName: String, variableName: String, action: Instruction, startValue: CodeGenExpression) - extends Instruction { - - override def init[E](generator: MethodStructure[E])(implicit context: CodeGenContext): Unit = { - startValue.init(generator) - val expression = startValue.generateExpression(generator) - generator.declareCounter(variableName, expression) - generator.ifStatement(generator.counterEqualsZero(variableName)) { onTrue => - onTrue.returnSuccessfully() - } - action.init(generator) - } - - override def body[E](generator: MethodStructure[E])(implicit context: CodeGenContext): Unit = { - action.body(generator) - - generator.trace(opName) { l1 => - l1.incrementRows() - l1.ifStatement(l1.decreaseCounterAndCheckForZero(variableName)) { l2 => - l2.returnSuccessfully() - } - } - } - - override protected def children: Seq[Instruction] = Seq(action) - - override protected def operatorId = Set(opName) -} diff --git a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/ExpandAllLoopDataGenerator.scala b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/ExpandAllLoopDataGenerator.scala deleted file mode 100644 index fdd69b616f529..0000000000000 --- a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/ExpandAllLoopDataGenerator.scala +++ /dev/null @@ -1,47 +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.compiler.v3_0.codegen.ir - -import org.neo4j.cypher.internal.compiler.v3_0.codegen.{CodeGenContext, MethodStructure, Variable} -import org.neo4j.cypher.internal.frontend.v3_0.SemanticDirection - -case class ExpandAllLoopDataGenerator(opName: String, fromVar: Variable, dir: SemanticDirection, - types: Map[String, String], toVar: Variable, relVar: Variable) - extends LoopDataGenerator { - - override def init[E](generator: MethodStructure[E])(implicit context: CodeGenContext) = { - generator.createRelExtractor(relVar.name) - types.foreach { - case (typeVar,relType) => generator.lookupRelationshipTypeId(typeVar, relType) - } - } - - override def produceIterator[E](iterVar: String, generator: MethodStructure[E])(implicit context: CodeGenContext) = { - if(types.isEmpty) - generator.nodeGetAllRelationships(iterVar, fromVar.name, dir) - else - generator.nodeGetRelationships(iterVar, fromVar.name, dir, types.keys.toSeq) - generator.incrementDbHits() - } - - override def produceNext[E](nextVar: Variable, iterVar: String, generator: MethodStructure[E]) - (implicit context: CodeGenContext) = - generator.nextRelationshipAndNode(toVar.name, iterVar, dir, fromVar.name, relVar.name) -} diff --git a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/ExpandIntoLoopDataGenerator.scala b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/ExpandIntoLoopDataGenerator.scala deleted file mode 100644 index 33ffc7d245bf6..0000000000000 --- a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/ExpandIntoLoopDataGenerator.scala +++ /dev/null @@ -1,47 +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.compiler.v3_0.codegen.ir - -import org.neo4j.cypher.internal.compiler.v3_0.codegen.{CodeGenContext, MethodStructure, Variable} -import org.neo4j.cypher.internal.frontend.v3_0.SemanticDirection - -case class ExpandIntoLoopDataGenerator(opName: String, fromVar: Variable, dir: SemanticDirection, - types: Map[String, String], toVar: Variable, relVar: Variable) - extends LoopDataGenerator { - - override def init[E](generator: MethodStructure[E])(implicit context: CodeGenContext) = { - generator.createRelExtractor(relVar.name) - types.foreach { - case (typeVar,relType) => generator.lookupRelationshipTypeId(typeVar, relType) - } - } - - override def produceIterator[E](iterVar: String, generator: MethodStructure[E])(implicit context: CodeGenContext) = { - if(types.isEmpty) - generator.connectingRelationships(iterVar, fromVar.name, dir, toVar.name) - else - generator.connectingRelationships(iterVar, fromVar.name, dir, types.keys.toSeq, toVar.name) - generator.incrementDbHits() - } - - override def produceNext[E](nextVar: Variable, iterVar: String, generator: MethodStructure[E]) - (implicit context: CodeGenContext) = - generator.nextRelationship(iterVar, dir, relVar.name) -} diff --git a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/ForEachExpression.scala b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/ForEachExpression.scala deleted file mode 100644 index deab307e74689..0000000000000 --- a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/ForEachExpression.scala +++ /dev/null @@ -1,40 +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.compiler.v3_0.codegen.ir - -import org.neo4j.cypher.internal.compiler.v3_0.codegen.ir.expressions.CodeGenExpression -import org.neo4j.cypher.internal.compiler.v3_0.codegen.{Variable, CodeGenContext, MethodStructure} -import org.neo4j.cypher.internal.frontend.v3_0.symbols - -case class ForEachExpression(varName: Variable, expression: CodeGenExpression, body: Instruction) extends Instruction { - - override def init[E](generator: MethodStructure[E])(implicit context: CodeGenContext) = { - expression.init(generator) - body.init(generator) - } - - override def body[E](generator: MethodStructure[E])(implicit context: CodeGenContext) = - - generator.forEach(varName.name, varName.cypherType, expression.generateExpression(generator)) { forBody => - body.body(forBody) - } - - override def children = Seq(body) -} diff --git a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/GetMatchesFromProbeTable.scala b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/GetMatchesFromProbeTable.scala deleted file mode 100644 index a30101d6ea8a7..0000000000000 --- a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/GetMatchesFromProbeTable.scala +++ /dev/null @@ -1,38 +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.compiler.v3_0.codegen.ir - -import org.neo4j.cypher.internal.compiler.v3_0.codegen.{Variable, CodeGenContext, MethodStructure} - -case class GetMatchesFromProbeTable(keys: Set[Variable], code: JoinData, action: Instruction) extends Instruction { - - override def body[E](generator: MethodStructure[E])(implicit context: CodeGenContext) = - generator.trace(code.id) { traced => - traced.probe(code.tableVar, code.tableType, keys.toSeq.map(_.name)) { body => - body.incrementRows() - action.body(body) - } - } - - override def init[E](generator: MethodStructure[E])(implicit context: CodeGenContext) = - action.init(generator) - - override def children = Seq(action) -} diff --git a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/If.scala b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/If.scala deleted file mode 100644 index 3418a5c8f9b6f..0000000000000 --- a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/If.scala +++ /dev/null @@ -1,39 +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.compiler.v3_0.codegen.ir - -import org.neo4j.cypher.internal.compiler.v3_0.codegen.ir.expressions.CodeGenExpression -import org.neo4j.cypher.internal.compiler.v3_0.codegen.{CodeGenContext, MethodStructure} - -case class If(predicate: CodeGenExpression, block: Instruction) extends Instruction { - override protected def children: Seq[Instruction] = Seq(block) - - override def body[E](generator: MethodStructure[E])(implicit context: CodeGenContext): Unit = { - generator.ifStatement(predicate.generateExpression(generator)) { inner => - inner.incrementRows() - block.body(inner) - } - } - - override def init[E](generator: MethodStructure[E])(implicit context: CodeGenContext): Unit = { - super.init(generator) - predicate.init(generator) - } -} diff --git a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/IndexSeek.scala b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/IndexSeek.scala deleted file mode 100644 index b1583c78c47ff..0000000000000 --- a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/IndexSeek.scala +++ /dev/null @@ -1,45 +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.compiler.v3_0.codegen.ir - -import org.neo4j.cypher.internal.compiler.v3_0.codegen.ir.expressions.CodeGenExpression -import org.neo4j.cypher.internal.compiler.v3_0.codegen.{Variable, CodeGenContext, MethodStructure} - -case class IndexSeek(opName: String, labelName: String, propName: String, descriptorVar: String, - expression: CodeGenExpression) extends LoopDataGenerator { - - override def init[E](generator: MethodStructure[E])(implicit context: CodeGenContext) = { - expression.init(generator) - val labelVar = context.namer.newVarName() - val propKeyVar = context.namer.newVarName() - generator.lookupLabelId(labelVar, labelName) - generator.lookupPropertyKey(propName, propKeyVar) - generator.newIndexDescriptor(descriptorVar, labelVar, propKeyVar) - } - - override def produceIterator[E](iterVar: String, generator: MethodStructure[E])(implicit context: CodeGenContext) = { - generator.indexSeek(iterVar, descriptorVar, expression.generateExpression(generator)) - generator.incrementDbHits() - } - - override def produceNext[E](nextVar: Variable, iterVar: String, generator: MethodStructure[E]) - (implicit context: CodeGenContext) = - generator.nextNode(nextVar.name, iterVar) -} diff --git a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/IndexUniqueSeek.scala b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/IndexUniqueSeek.scala deleted file mode 100644 index acf4d1c12fd65..0000000000000 --- a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/IndexUniqueSeek.scala +++ /dev/null @@ -1,53 +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.compiler.v3_0.codegen.ir - -import org.neo4j.cypher.internal.compiler.v3_0.codegen.ir.expressions.CodeGenExpression -import org.neo4j.cypher.internal.compiler.v3_0.codegen.{CodeGenContext, MethodStructure, Variable} - -case class IndexUniqueSeek(opName: String, labelName: String, propName: String, descriptorVar: String, - expression: CodeGenExpression, node: Variable, inner: Instruction) extends Instruction { - - override def init[E](generator: MethodStructure[E])(implicit context: CodeGenContext) = { - super.init(generator) - expression.init(generator) - val labelVar = context.namer.newVarName() - val propKeyVar = context.namer.newVarName() - generator.lookupLabelId(labelVar, labelName) - generator.lookupPropertyKey(propName, propKeyVar) - generator.newIndexDescriptor(descriptorVar, labelVar, propKeyVar) - } - - override def body[E](generator: MethodStructure[E])(implicit context: CodeGenContext) = { - generator.trace(opName) { body => - body.incrementDbHits() - body.indexUniqueSeek(node.name, descriptorVar, expression.generateExpression(body)) - body.ifStatement(body.notNull(node.name, node.cypherType)) { ifBody => - ifBody.incrementRows() - inner.body(ifBody) - } - - } - } - - override protected def children: Seq[Instruction] = Seq(inner) - - override protected def operatorId: Set[String] = Set(opName) -} diff --git a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/Instruction.scala b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/Instruction.scala deleted file mode 100644 index 063080b9d8f19..0000000000000 --- a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/Instruction.scala +++ /dev/null @@ -1,49 +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.compiler.v3_0.codegen.ir - -import org.neo4j.cypher.internal.compiler.v3_0.codegen.{CodeGenContext, MethodStructure} - -trait Instruction { - def init[E](generator: MethodStructure[E])(implicit context: CodeGenContext): Unit = children.foreach(_.init(generator)) - def body[E](generator: MethodStructure[E])(implicit context: CodeGenContext): Unit - - protected def children: Seq[Instruction] - - private def treeView: Seq[Instruction] = { - children.foldLeft(Seq(this)) { (acc, child) => acc ++ child.treeView } - } - - // Aggregating methods -- final to prevent overriding - final def allOperatorIds: Set[String] = treeView.flatMap(_.operatorId).toSet - - protected def operatorId: Set[String] = Set.empty -} - -object Instruction { - - val empty = new Instruction { - override def body[E](generator: MethodStructure[E])(implicit context: CodeGenContext) = {} - - override protected def children = Seq.empty - - override def init[E](generator: MethodStructure[E])(implicit context: CodeGenContext) = {} - } -} diff --git a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/LoopDataGenerator.scala b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/LoopDataGenerator.scala deleted file mode 100644 index 4c8bf02b29f5b..0000000000000 --- a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/LoopDataGenerator.scala +++ /dev/null @@ -1,33 +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.compiler.v3_0.codegen.ir - -import org.neo4j.cypher.internal.compiler.v3_0.codegen.{Variable, CodeGenContext, MethodStructure} - -// Generates the code that moves data into local variables from the iterator being consumed -trait LoopDataGenerator { - def init[E](generator: MethodStructure[E])(implicit context: CodeGenContext): Unit - - def produceNext[E](nextVar: Variable, iterVar: String, generator: MethodStructure[E])(implicit context: CodeGenContext): Unit - - def produceIterator[E](iterVarName: String, generator: MethodStructure[E])(implicit context: CodeGenContext): Unit - - def opName: String -} diff --git a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/MethodInvocation.scala b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/MethodInvocation.scala deleted file mode 100644 index d498f3f515022..0000000000000 --- a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/MethodInvocation.scala +++ /dev/null @@ -1,39 +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.compiler.v3_0.codegen.ir - -import org.neo4j.cypher.internal.compiler.v3_0.codegen._ - -case class MethodInvocation(override val operatorId: Set[String], - symbol:JoinTableMethod, - methodName: String, - statements: Seq[Instruction]) extends Instruction { - - override def init[E](generator: MethodStructure[E])(implicit context: CodeGenContext) = {} - - override def body[E](generator: MethodStructure[E])(implicit context: CodeGenContext) = { - generator.method(symbol.tableType, symbol.name, methodName) { body => - statements.foreach(_.init(body)) - statements.foreach(_.body(body)) - } - } - - override def children = statements -} diff --git a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/NullingInstruction.scala b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/NullingInstruction.scala deleted file mode 100644 index 978b9aa2bcd82..0000000000000 --- a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/NullingInstruction.scala +++ /dev/null @@ -1,46 +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.compiler.v3_0.codegen.ir - -import org.neo4j.cypher.internal.compiler.v3_0.codegen.{CodeGenContext, MethodStructure, Variable} - -/** - * Generates code that runs and afterwards checks if the provided variable has been set, - * if not it sets all provided variables to null and runs the alternativeAction - */ -case class NullingInstruction(loop: Instruction, yieldedFlagVar: String, alternativeAction: Instruction, - nullableVars: Variable*) - extends Instruction { - - override def init[E](generator: MethodStructure[E])(implicit context: CodeGenContext) = - loop.init(generator) - - override def body[E](generator: MethodStructure[E])(implicit context: CodeGenContext) = { - generator.declareFlag(yieldedFlagVar, initialValue = false) - loop.body(generator) - generator.ifStatement(generator.threeValuedNot(generator.load(yieldedFlagVar))){ ifBody => - //mark variables as null - nullableVars.foreach(v => ifBody.markAsNull(v.name, v.cypherType)) - alternativeAction.body(ifBody) - } - } - - override def children = Seq(loop) -} diff --git a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/Projection.scala b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/Projection.scala deleted file mode 100644 index 5667c3cf8c610..0000000000000 --- a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/Projection.scala +++ /dev/null @@ -1,48 +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.compiler.v3_0.codegen.ir - -import org.neo4j.cypher.internal.compiler.v3_0.codegen.ir.expressions.CodeGenExpression -import org.neo4j.cypher.internal.compiler.v3_0.codegen.{CodeGenContext, MethodStructure, Variable} - -case class Projection(projectionOpName: String, variables: Map[Variable, CodeGenExpression], action: Instruction) - extends Instruction { - - override def init[E](generator: MethodStructure[E])(implicit context: CodeGenContext) = { - super.init(generator) - variables.foreach { - case (_, expr) => expr.init(generator) - } - } - - override def body[E](generator: MethodStructure[E])(implicit context: CodeGenContext) = { - generator.trace(projectionOpName) { body => - body.incrementRows() - variables.foreach { - case (variable, expr) => body.projectVariable(variable.name, expr.generateExpression(body)) - } - action.body(body) - } - } - - override protected def operatorId = Set(projectionOpName) - - override protected def children = Seq(action) -} diff --git a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/ScanAllNodes.scala b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/ScanAllNodes.scala deleted file mode 100644 index 533483e3c7768..0000000000000 --- a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/ScanAllNodes.scala +++ /dev/null @@ -1,36 +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.compiler.v3_0.codegen.ir - -import org.neo4j.cypher.internal.compiler.v3_0.codegen.{Variable, CodeGenContext, MethodStructure} - -case class ScanAllNodes(opName: String) extends LoopDataGenerator { - - override def init[E](generator: MethodStructure[E])(implicit context: CodeGenContext) = {} - - override def produceIterator[E](iterVar: String, generator: MethodStructure[E])(implicit context: CodeGenContext) = { - generator.allNodesScan(iterVar) - generator.incrementDbHits() - } - - override def produceNext[E](nextVar: Variable, iterVar: String, generator: MethodStructure[E]) - (implicit context: CodeGenContext) = - generator.nextNode(nextVar.name, iterVar) -} diff --git a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/ScanForLabel.scala b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/ScanForLabel.scala deleted file mode 100644 index 32663dd08a01b..0000000000000 --- a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/ScanForLabel.scala +++ /dev/null @@ -1,37 +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.compiler.v3_0.codegen.ir - -import org.neo4j.cypher.internal.compiler.v3_0.codegen.{Variable, CodeGenContext, MethodStructure} - -case class ScanForLabel(opName: String, labelName: String, labelVar: String) extends LoopDataGenerator { - - override def init[E](generator: MethodStructure[E])(implicit context: CodeGenContext) = - generator.lookupLabelId(labelVar, labelName) - - override def produceIterator[E](iterVar: String, generator: MethodStructure[E])(implicit context: CodeGenContext) = { - generator.labelScan(iterVar, labelVar) - generator.incrementDbHits() - } - - override def produceNext[E](nextVar: Variable, iterVar: String, generator: MethodStructure[E]) - (implicit context: CodeGenContext) = - generator.nextNode(nextVar.name, iterVar) -} diff --git a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/SelectionInstruction.scala b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/SelectionInstruction.scala deleted file mode 100644 index f1eccd839b020..0000000000000 --- a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/SelectionInstruction.scala +++ /dev/null @@ -1,36 +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.compiler.v3_0.codegen.ir - -import org.neo4j.cypher.internal.compiler.v3_0.codegen.{CodeGenContext, MethodStructure} - -case class SelectionInstruction(id: String, instruction: Instruction) extends Instruction { - - override def init[E](generator: MethodStructure[E])(implicit context: CodeGenContext) = super.init(generator) - - override def body[E](generator: MethodStructure[E])(implicit context: CodeGenContext) = - generator.trace(id) { body => - instruction.body(body) - } - - override def children = Seq(instruction) - - override protected def operatorId = Set(id) -} diff --git a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/WhileLoop.scala b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/WhileLoop.scala deleted file mode 100644 index 0670cf731bceb..0000000000000 --- a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/WhileLoop.scala +++ /dev/null @@ -1,47 +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.compiler.v3_0.codegen.ir - -import org.neo4j.cypher.internal.compiler.v3_0.codegen.{Variable, CodeGenContext, MethodStructure} - -case class WhileLoop(variable: Variable, producer: LoopDataGenerator, action: Instruction) extends Instruction { - - override def body[E](generator: MethodStructure[E])(implicit context: CodeGenContext) = { - val iterator = s"${variable.name}Iter" - generator.trace(producer.opName) { body => - producer.produceIterator(iterator, body) - body.whileLoop(body.hasNext(iterator)) { loopBody => - loopBody.incrementDbHits() - loopBody.incrementRows() - producer.produceNext(variable, iterator, loopBody) - action.body(loopBody) - } - } - } - - override def operatorId: Set[String] = Set(producer.opName) - - override def children = Seq(action) - - override def init[E](generator: MethodStructure[E])(implicit context: CodeGenContext): Unit = { - super.init(generator) - producer.init(generator) - } -} diff --git a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/Addition.scala b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/Addition.scala deleted file mode 100644 index c0518aa06bfaa..0000000000000 --- a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/Addition.scala +++ /dev/null @@ -1,53 +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.compiler.v3_0.codegen.ir.expressions - -import org.neo4j.cypher.internal.compiler.v3_0.codegen.{CodeGenContext, MethodStructure} -import org.neo4j.cypher.internal.frontend.v3_0.symbols._ - -case class Addition(lhs: CodeGenExpression, rhs: CodeGenExpression) extends CodeGenExpression with BinaryOperator { - - override protected def generator[E](structure: MethodStructure[E])(implicit context: CodeGenContext) = structure.add - - override def nullable(implicit context: CodeGenContext) = lhs.nullable || rhs.nullable - - val validTypes = Seq(CTString, CTFloat, CTInteger, CTList(CTAny)) - - override def cypherType(implicit context: CodeGenContext) = (lhs.cypherType, rhs.cypherType) match { - // Strings - case (CTString, CTString) => CTString - - // Collections - case (ListType(left), ListType(right)) => ListType(left leastUpperBound right) - case (ListType(innerType), singleElement) => ListType(innerType leastUpperBound singleElement) - case (singleElement, ListType(innerType)) => ListType(innerType leastUpperBound singleElement) - - // Numbers - case (CTInteger, CTInteger) => CTInteger - case (Number(_), Number(_)) => CTFloat - - // Runtime we'll figure it out - case _ => CTAny - } - - object Number { - def unapply(x: CypherType): Option[CypherType] = if (CTNumber.isAssignableFrom(x)) Some(x) else None - } -} diff --git a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/BinaryOperator.scala b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/BinaryOperator.scala deleted file mode 100644 index 068046d7d9da4..0000000000000 --- a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/BinaryOperator.scala +++ /dev/null @@ -1,56 +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.compiler.v3_0.codegen.ir.expressions - -import org.neo4j.cypher.internal.compiler.v3_0.codegen.{CodeGenContext, MethodStructure} -import org.neo4j.cypher.internal.frontend.v3_0.symbols._ - -trait BinaryOperator { - self: CodeGenExpression => - - def lhs: CodeGenExpression - def rhs: CodeGenExpression - - override final def init[E](generator: MethodStructure[E])(implicit context: CodeGenContext) = { - lhs.init(generator) - rhs.init(generator) - } - - override final def generateExpression[E](structure: MethodStructure[E])(implicit context: CodeGenContext) = - generator(structure)(context)(lhs.generateExpression(structure), rhs.generateExpression(structure)) - - protected def generator[E](structure: MethodStructure[E])(implicit context: CodeGenContext): (E, E) => E -} - -// Trait that resolves type based on inputs. -trait NumericalOpType { - self : CodeGenExpression => - - def lhs: CodeGenExpression - def rhs: CodeGenExpression - - override def cypherType(implicit context: CodeGenContext) = - (lhs.cypherType, rhs.cypherType) match { - case (CTInteger, CTInteger) => CTInteger - case (_: NumberType, _: NumberType) => CTFloat - // Runtime we'll figure it out - can't store it in a primitive field unless we are 100% of the type - case _ => CTAny - } -} diff --git a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/CastToCollection.scala b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/CastToCollection.scala deleted file mode 100644 index b79f620c5a554..0000000000000 --- a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/CastToCollection.scala +++ /dev/null @@ -1,35 +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.compiler.v3_0.codegen.ir.expressions - -import org.neo4j.cypher.internal.compiler.v3_0.codegen.{CodeGenContext, MethodStructure} -import org.neo4j.cypher.internal.frontend.v3_0.symbols._ - -case class CastToCollection(expression: CodeGenExpression) extends CodeGenExpression { - - override def init[E](generator: MethodStructure[E])(implicit context: CodeGenContext) = expression.init(generator) - - override def generateExpression[E](structure: MethodStructure[E])(implicit context: CodeGenContext) = - structure.castToCollection(expression.generateExpression(structure)) - - override def nullable(implicit context: CodeGenContext) = expression.nullable - - override def cypherType(implicit context: CodeGenContext) = CTList(CTAny) -} diff --git a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/CodeGenExpression.scala b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/CodeGenExpression.scala deleted file mode 100644 index 81f912b275fbf..0000000000000 --- a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/CodeGenExpression.scala +++ /dev/null @@ -1,30 +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.compiler.v3_0.codegen.ir.expressions - -import org.neo4j.cypher.internal.compiler.v3_0.codegen.{CodeGenContext, MethodStructure} -import org.neo4j.cypher.internal.frontend.v3_0.symbols.CypherType - -trait CodeGenExpression { - def init[E](generator: MethodStructure[E])(implicit context: CodeGenContext): Unit - def generateExpression[E](structure: MethodStructure[E])(implicit context: CodeGenContext): E - def nullable(implicit context: CodeGenContext): Boolean - def cypherType(implicit context: CodeGenContext): CypherType -} diff --git a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/Collection.scala b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/Collection.scala deleted file mode 100644 index 633098fed5f1b..0000000000000 --- a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/Collection.scala +++ /dev/null @@ -1,42 +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.compiler.v3_0.codegen.ir.expressions - -import org.neo4j.cypher.internal.compiler.v3_0.codegen.{CodeGenContext, MethodStructure} -import org.neo4j.cypher.internal.frontend.v3_0.symbols._ - -case class Collection(expressions: Seq[CodeGenExpression]) extends CodeGenExpression { - - override def init[E](generator: MethodStructure[E])(implicit context: CodeGenContext) = - expressions.foreach { instruction => - instruction.init(generator) - } - - override def generateExpression[E](structure: MethodStructure[E])(implicit context: CodeGenContext) = - structure.asList(expressions.map(_.generateExpression(structure))) - - override def nullable(implicit context: CodeGenContext) = false - - override def cypherType(implicit context: CodeGenContext) = { - val commonType = expressions.map(_.cypherType).reduce[CypherType](_ leastUpperBound _) - - CTList(commonType) - } -} diff --git a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/Division.scala b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/Division.scala deleted file mode 100644 index 6f0599f8471c2..0000000000000 --- a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/Division.scala +++ /dev/null @@ -1,30 +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.compiler.v3_0.codegen.ir.expressions - -import org.neo4j.cypher.internal.compiler.v3_0.codegen.{CodeGenContext, MethodStructure} - -case class Division(lhs: CodeGenExpression, rhs: CodeGenExpression) - extends CodeGenExpression with BinaryOperator with NumericalOpType { - - override protected def generator[E](structure: MethodStructure[E])(implicit context: CodeGenContext) = structure.div - - override def nullable(implicit context: CodeGenContext) = lhs.nullable || rhs.nullable -} diff --git a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/Equals.scala b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/Equals.scala deleted file mode 100644 index ea76fead45417..0000000000000 --- a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/Equals.scala +++ /dev/null @@ -1,50 +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.compiler.v3_0.codegen.ir.expressions - -import org.neo4j.cypher.internal.compiler.v3_0.codegen.{CodeGenContext, MethodStructure} -import org.neo4j.cypher.internal.frontend.v3_0.{IncomparableValuesException, symbols} - -case class Equals(lhs: CodeGenExpression, rhs: CodeGenExpression) extends CodeGenExpression { - - override def nullable(implicit context: CodeGenContext) = lhs.nullable || rhs.nullable - - override def cypherType(implicit context: CodeGenContext) = symbols.CTBoolean - - override def init[E](generator: MethodStructure[E])(implicit context: CodeGenContext) = { - lhs.init(generator) - rhs.init(generator) - } - - override def generateExpression[E](structure: MethodStructure[E])(implicit context: CodeGenContext) = { - if (nullable) structure.threeValuedEquals(lhs.generateExpression(structure), rhs.generateExpression(structure)) - else (lhs, rhs) match { - case (NodeExpression(v1), NodeExpression(v2)) => structure.eq(structure.load(v1.name), structure.load(v2.name)) - case (RelationshipExpression(v1), RelationshipExpression(v2)) => structure.eq(structure.load(v1.name), structure.load(v2.name)) - case (NodeExpression(_), RelationshipExpression(_)) => throw new - IncomparableValuesException(symbols.CTNode.toString, symbols.CTRelationship.toString) - case (RelationshipExpression(_), NodeExpression(_)) => throw new - IncomparableValuesException(symbols.CTNode.toString, symbols.CTRelationship.toString) - case _ => structure.threeValuedEquals(lhs.generateExpression(structure), rhs.generateExpression(structure)) - } - } - - -} diff --git a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/ExpressionConverter.scala b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/ExpressionConverter.scala deleted file mode 100644 index f37f21c96f099..0000000000000 --- a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/ExpressionConverter.scala +++ /dev/null @@ -1,165 +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.compiler.v3_0.codegen.ir.expressions - -import org.neo4j.cypher.internal.compiler.v3_0.codegen.ir.expressions -import org.neo4j.cypher.internal.compiler.v3_0.codegen.ir.functions.functionConverter -import org.neo4j.cypher.internal.compiler.v3_0.codegen.{CodeGenContext, MethodStructure} -import org.neo4j.cypher.internal.compiler.v3_0.planner.CantCompileQueryException -import org.neo4j.cypher.internal.frontend.v3_0.symbols.{CTNode, CTRelationship} -import org.neo4j.cypher.internal.frontend.v3_0.{InternalException, ast, symbols} - -object ExpressionConverter { - - implicit class ExpressionToPredicate(expression: CodeGenExpression) { - - def asPredicate = new CodeGenExpression { - - override def generateExpression[E](structure: MethodStructure[E])(implicit context: CodeGenContext) = { - if (expression.nullable) structure.coerceToBoolean(expression.generateExpression(structure)) - else expression.generateExpression(structure) - } - - override def init[E](generator: MethodStructure[E])(implicit context: CodeGenContext) = expression.init(generator) - - override def nullable(implicit context: CodeGenContext) = false - - override def cypherType(implicit context: CodeGenContext) = symbols.CTBoolean - } - } - - def createPredicate(expression: ast.Expression) - (implicit context: CodeGenContext): CodeGenExpression = expression match { - case ast.HasLabels(ast.Variable(name), label :: Nil) => - val labelIdVariable = context.namer.newVarName() - val nodeVariable = context.getVariable(name) - HasLabel(nodeVariable, labelIdVariable, label.name).asPredicate - - case exp@ast.Property(node@ast.Variable(name), propKey) if context.semanticTable.isNode(node) => - createExpression(exp).asPredicate - - case exp@ast.Property(node@ast.Variable(name), propKey) if context.semanticTable.isRelationship(node) => - createExpression(exp).asPredicate - - case ast.Not(e) => Not(createExpression(e)).asPredicate - - case ast.Equals(lhs, rhs) => Equals(createExpression(lhs), createExpression(rhs)).asPredicate - - case ast.Or(lhs, rhs) => Or(createExpression(lhs), createExpression(rhs)).asPredicate - - case other => - throw new CantCompileQueryException(s"Predicate of $other not yet supported") - - } - - def createExpression(expression: ast.Expression) - (implicit context: CodeGenContext): CodeGenExpression = expressionConverter(expression, createExpression) - - def createProjection(expression: ast.Expression) - (implicit context: CodeGenContext): CodeGenExpression = { - - expression match { - case node@ast.Variable(name) if context.semanticTable.isNode(node) => - NodeProjection(context.getVariable(name)) - - case rel@ast.Variable(name) if context.semanticTable.isRelationship(rel) => - RelationshipProjection(context.getVariable(name)) - - case e => expressionConverter(e, createProjection) - } - } - - def createExpressionForVariable(variableQueryVariable: String) - (implicit context: CodeGenContext): CodeGenExpression = { - - val variable = context.getVariable(variableQueryVariable) - - variable.cypherType match { - case CTNode => NodeProjection(variable) - case CTRelationship => RelationshipProjection(variable) - case _ => throw new InternalException("The compiled runtime only handles variables pointing to rels and nodes at this time") - } - } - - private def expressionConverter(expression: ast.Expression, callback: ast.Expression => CodeGenExpression) - (implicit context: CodeGenContext): CodeGenExpression = { - - expression match { - case node@ast.Variable(name) if context.semanticTable.isNode(node) => - NodeExpression(context.getVariable(name)) - - case rel@ast.Variable(name) if context.semanticTable.isRelationship(rel) => - RelationshipExpression(context.getVariable(name)) - - case ast.Property(node@ast.Variable(name), propKey) if context.semanticTable.isNode(node) => - val token = propKey.id(context.semanticTable).map(_.id) - NodeProperty(token, propKey.name, context.getVariable(name), context.namer.newVarName()) - - case ast.Property(rel@ast.Variable(name), propKey) if context.semanticTable.isRelationship(rel) => - val token = propKey.id(context.semanticTable).map(_.id) - RelProperty(token, propKey.name, context.getVariable(name), context.namer.newVarName()) - - case ast.Parameter(name, _) => expressions.Parameter(name, context.namer.newVarName()) - - case lit: ast.IntegerLiteral => Literal(lit.value) - - case lit: ast.DoubleLiteral => Literal(lit.value) - - case lit: ast.StringLiteral => Literal(lit.value) - - case lit: ast.Literal => Literal(lit.value) - - case ast.Collection(exprs) => - expressions.Collection(exprs.map(e => callback(e))) - - case ast.Add(lhs, rhs) => - val leftOp = callback(lhs) - val rightOp = callback(rhs) - Addition(leftOp, rightOp) - - case ast.Subtract(lhs, rhs) => - val leftOp = callback(lhs) - val rightOp = callback(rhs) - Subtraction(leftOp, rightOp) - - case ast.MapExpression(items) => - val map = items.map { - case (key, expr) => (key.name, callback(expr)) - }.toMap - MyMap(map) - - case ast.HasLabels(ast.Variable(name), label :: Nil) => - val labelIdVariable = context.namer.newVarName() - val nodeVariable = context.getVariable(name) - HasLabel(nodeVariable, labelIdVariable, label.name) - - case ast.Equals(lhs, rhs) => Equals(callback(lhs), callback(rhs)) - - case ast.Or(lhs, rhs) => Or(callback(lhs), callback(rhs)) - - case ast.Not(inner) => Not(callback(inner)) - - case f: ast.FunctionInvocation => functionConverter(f, callback) - - case other => throw new CantCompileQueryException(s"Expression of $other not yet supported") - } - } - -} diff --git a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/HasLabel.scala b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/HasLabel.scala deleted file mode 100644 index aee8394503af6..0000000000000 --- a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/HasLabel.scala +++ /dev/null @@ -1,46 +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.compiler.v3_0.codegen.ir.expressions - -import org.neo4j.cypher.internal.compiler.v3_0.codegen.{CodeGenContext, MethodStructure, Variable} -import org.neo4j.cypher.internal.frontend.v3_0.symbols.{CypherType, _} - -case class HasLabel(nodeVariable: Variable, labelVariable: String, labelName: String) - extends CodeGenExpression { - - def init[E](generator: MethodStructure[E])(implicit context: CodeGenContext) = - generator.lookupLabelId(labelVariable, labelName) - - def generateExpression[E](structure: MethodStructure[E])(implicit context: CodeGenContext) = { - val localName = context.namer.newVarName() - structure.declarePredicate(localName) - - structure.incrementDbHits() - if (nodeVariable.nullable) - structure.nullable(nodeVariable.name, nodeVariable.cypherType, - structure.hasLabel(nodeVariable.name, labelVariable, localName)) - else - structure.hasLabel(nodeVariable.name, labelVariable, localName) - } - - override def nullable(implicit context: CodeGenContext) = nodeVariable.nullable - - override def cypherType(implicit context: CodeGenContext): CypherType = CTBoolean -} diff --git a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/Literal.scala b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/Literal.scala deleted file mode 100644 index b5f3a5b33e76e..0000000000000 --- a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/Literal.scala +++ /dev/null @@ -1,36 +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.compiler.v3_0.codegen.ir.expressions - -import org.neo4j.cypher.internal.compiler.v3_0.codegen.{CodeGenContext, MethodStructure} -import org.neo4j.cypher.internal.compiler.v3_0.helpers.LiteralTypeSupport - -case class Literal(value: Object) extends CodeGenExpression { - - override def init[E](generator: MethodStructure[E])(implicit context: CodeGenContext) = {} - - override def generateExpression[E](structure: MethodStructure[E])(implicit context: CodeGenContext) = - structure.constant(value) - - override def nullable(implicit context: CodeGenContext) = value == null - - override def cypherType(implicit context: CodeGenContext) = - LiteralTypeSupport.deriveType(value) -} diff --git a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/LoadVariable.scala b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/LoadVariable.scala deleted file mode 100644 index 206c9f9d3d6c6..0000000000000 --- a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/LoadVariable.scala +++ /dev/null @@ -1,34 +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.compiler.v3_0.codegen.ir.expressions - -import org.neo4j.cypher.internal.compiler.v3_0.codegen.{Variable, CodeGenContext, MethodStructure} -import org.neo4j.cypher.internal.frontend.v3_0.symbols.CypherType - -case class LoadVariable(variable: Variable) extends CodeGenExpression { - - override def init[E](generator: MethodStructure[E])(implicit context: CodeGenContext) = {} - - override def generateExpression[E](structure: MethodStructure[E])(implicit context: CodeGenContext) = - structure.load(variable.name) - - override def nullable(implicit context: CodeGenContext): Boolean = variable.nullable - override def cypherType(implicit context: CodeGenContext): CypherType = variable.cypherType -} diff --git a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/Modulo.scala b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/Modulo.scala deleted file mode 100644 index 6258ddf6929ef..0000000000000 --- a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/Modulo.scala +++ /dev/null @@ -1,32 +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.compiler.v3_0.codegen.ir.expressions - -import org.neo4j.cypher.internal.compiler.v3_0.codegen.{CodeGenContext, MethodStructure} -import org.neo4j.cypher.internal.frontend.v3_0.symbols._ - -case class Modulo(lhs: CodeGenExpression, rhs: CodeGenExpression) extends CodeGenExpression with BinaryOperator { - - override protected def generator[E](structure: MethodStructure[E])(implicit context: CodeGenContext) = structure.mod - - override def nullable(implicit context: CodeGenContext) = lhs.nullable || rhs.nullable - - override def cypherType(implicit context: CodeGenContext) = CTFloat -} diff --git a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/Multiplication.scala b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/Multiplication.scala deleted file mode 100644 index a9daa8d405bb2..0000000000000 --- a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/Multiplication.scala +++ /dev/null @@ -1,30 +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.compiler.v3_0.codegen.ir.expressions - -import org.neo4j.cypher.internal.compiler.v3_0.codegen.{CodeGenContext, MethodStructure} - -case class Multiplication(lhs: CodeGenExpression, rhs: CodeGenExpression) - extends CodeGenExpression with BinaryOperator with NumericalOpType { - - override def nullable(implicit context: CodeGenContext) = lhs.nullable || rhs.nullable - - override protected def generator[E](structure: MethodStructure[E])(implicit context: CodeGenContext) = structure.mul -} diff --git a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/MyMap.scala b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/MyMap.scala deleted file mode 100644 index 86b7e60968a75..0000000000000 --- a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/MyMap.scala +++ /dev/null @@ -1,39 +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.compiler.v3_0.codegen.ir.expressions - -import org.neo4j.cypher.internal.compiler.v3_0.codegen.{CodeGenContext, MethodStructure} -import org.neo4j.cypher.internal.frontend.v3_0.symbols._ - -//Named MyMap to avoid conflict with collection.Map which makes everything weird -case class MyMap(instructions: Map[String, CodeGenExpression]) extends CodeGenExpression { - - override def init[E](generator: MethodStructure[E])(implicit context: CodeGenContext) = - instructions.values.foreach { instruction => - instruction.init(generator) - } - - override def generateExpression[E](structure: MethodStructure[E])(implicit context: CodeGenContext) = - structure.asMap(instructions.mapValues(_.generateExpression(structure))) - - override def nullable(implicit context: CodeGenContext) = false - - override def cypherType(implicit context: CodeGenContext) = CTMap -} diff --git a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/NodeExpression.scala b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/NodeExpression.scala deleted file mode 100644 index 4b1714d6fb8d0..0000000000000 --- a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/NodeExpression.scala +++ /dev/null @@ -1,41 +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.compiler.v3_0.codegen.ir.expressions - -import org.neo4j.cypher.internal.compiler.v3_0.codegen.{CodeGenContext, MethodStructure, Variable} -import org.neo4j.cypher.internal.frontend.v3_0.symbols -import org.neo4j.cypher.internal.frontend.v3_0.symbols._ - -case class NodeExpression(nodeIdVar: Variable) extends CodeGenExpression { - assert(nodeIdVar.cypherType == symbols.CTNode) - - override def init[E](generator: MethodStructure[E])(implicit context: CodeGenContext) = {} - - override def generateExpression[E](structure: MethodStructure[E])(implicit context: CodeGenContext) = { - if (nodeIdVar.nullable) - structure.nullable(nodeIdVar.name, nodeIdVar.cypherType, structure.node(nodeIdVar.name)) - else - structure.node(nodeIdVar.name) - } - - override def nullable(implicit context: CodeGenContext) = nodeIdVar.nullable - - override def cypherType(implicit context: CodeGenContext) = CTNode -} diff --git a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/NodeProjection.scala b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/NodeProjection.scala deleted file mode 100644 index 904e63f00e38e..0000000000000 --- a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/NodeProjection.scala +++ /dev/null @@ -1,41 +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.compiler.v3_0.codegen.ir.expressions - -import org.neo4j.cypher.internal.compiler.v3_0.codegen.{Variable, CodeGenContext, MethodStructure} -import org.neo4j.cypher.internal.frontend.v3_0.symbols -import org.neo4j.cypher.internal.frontend.v3_0.symbols._ - -case class NodeProjection(nodeIdVar: Variable) extends CodeGenExpression { - assert(nodeIdVar.cypherType == symbols.CTNode) - - override def init[E](generator: MethodStructure[E])(implicit context: CodeGenContext) = {} - - override def generateExpression[E](structure: MethodStructure[E])(implicit context: CodeGenContext) ={ - if (nodeIdVar.nullable) - structure.nullable(nodeIdVar.name, nodeIdVar.cypherType, structure.materializeNode(nodeIdVar.name)) - else - structure.materializeNode(nodeIdVar.name) - } - - override def nullable(implicit context: CodeGenContext) = nodeIdVar.nullable - - override def cypherType(implicit context: CodeGenContext) = CTNode -} diff --git a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/NodeProperty.scala b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/NodeProperty.scala deleted file mode 100644 index fa554ee0ef74b..0000000000000 --- a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/NodeProperty.scala +++ /dev/null @@ -1,90 +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.compiler.v3_0.codegen.ir.expressions - -import org.neo4j.cypher.internal.compiler.v3_0.codegen.{CodeGenContext, MethodStructure, Variable} -import org.neo4j.cypher.internal.frontend.v3_0.symbols._ - -abstract class ElementProperty(token: Option[Int], propName: String, elementIdVar: String, propKeyVar: String) - extends CodeGenExpression { - override def init[E](generator: MethodStructure[E])(implicit context: CodeGenContext) = - if (token.isEmpty) generator.lookupPropertyKey(propName, propKeyVar) - - override def generateExpression[E](structure: MethodStructure[E])(implicit context: CodeGenContext): E = { - val localName = context.namer.newVarName() - structure.declareProperty(localName) - if (token.isEmpty) - propertyByName(structure, localName) - else - propertyById(structure, localName) - structure.incrementDbHits() - structure.load(localName) - } - - def propertyByName[E](body: MethodStructure[E], localName: String): Unit - - def propertyById[E](body: MethodStructure[E], localName: String): Unit - - override def nullable(implicit context: CodeGenContext) = true -} - -case class NodeProperty(token: Option[Int], propName: String, nodeIdVar: Variable, propKeyVar: String) - extends ElementProperty(token, propName, nodeIdVar.name, propKeyVar) { - - override def propertyByName[E](body: MethodStructure[E], localName: String) = - if (nodeIdVar.nullable) - body.ifStatement(body.notNull(nodeIdVar.name, nodeIdVar.cypherType)) {ifBody => - ifBody.nodeGetPropertyForVar(nodeIdVar.name, propKeyVar, localName) - } - else - body.nodeGetPropertyForVar(nodeIdVar.name, propKeyVar, localName) - - override def propertyById[E](body: MethodStructure[E], localName: String) = - if (nodeIdVar.nullable) - body.ifStatement(body.notNull(nodeIdVar.name, nodeIdVar.cypherType)) {ifBody => - ifBody.nodeGetPropertyById(nodeIdVar.name, token.get, localName) - } - else - body.nodeGetPropertyById(nodeIdVar.name, token.get, localName) - - override def cypherType(implicit context: CodeGenContext) = CTAny -} - -case class RelProperty(token: Option[Int], propName: String, relIdVar: Variable, propKeyVar: String) - extends ElementProperty(token, propName, relIdVar.name, propKeyVar) { - - override def propertyByName[E](body: MethodStructure[E], localName: String) = - if (relIdVar.nullable) - body.ifStatement(body.notNull(relIdVar.name, relIdVar.cypherType)) { ifBody => - ifBody.relationshipGetPropertyForVar(relIdVar.name, propKeyVar, localName) - } - else - body.relationshipGetPropertyForVar(relIdVar.name, propKeyVar, localName) - - override def propertyById[E](body: MethodStructure[E], localName: String) = - if (relIdVar.nullable) - body.ifStatement(body.notNull(relIdVar.name, relIdVar.cypherType)) { ifBody => - ifBody.relationshipGetPropertyById(relIdVar.name, token.get, localName) - } - else - body.relationshipGetPropertyById(relIdVar.name, token.get, localName) - - override def cypherType(implicit context: CodeGenContext) = CTAny -} diff --git a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/Not.scala b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/Not.scala deleted file mode 100644 index b0467e2ca5332..0000000000000 --- a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/Not.scala +++ /dev/null @@ -1,38 +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.compiler.v3_0.codegen.ir.expressions - -import org.neo4j.cypher.internal.compiler.v3_0.codegen.{CodeGenContext, MethodStructure} -import org.neo4j.cypher.internal.frontend.v3_0.symbols - -case class Not(inner: CodeGenExpression) extends CodeGenExpression { - - override def init[E](generator: MethodStructure[E])(implicit context: CodeGenContext) = { - inner.init(generator) - } - - override def generateExpression[E](structure: MethodStructure[E])(implicit context: CodeGenContext) = - if (!nullable && inner.cypherType == symbols.CTBoolean) structure.not(inner.generateExpression(structure)) - else structure.threeValuedNot(inner.generateExpression(structure)) - - override def nullable(implicit context: CodeGenContext) = inner.nullable - - override def cypherType(implicit context: CodeGenContext) = symbols.CTBoolean -} diff --git a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/Or.scala b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/Or.scala deleted file mode 100644 index f6cf355f44611..0000000000000 --- a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/Or.scala +++ /dev/null @@ -1,34 +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.compiler.v3_0.codegen.ir.expressions - -import org.neo4j.cypher.internal.compiler.v3_0.codegen.{CodeGenContext, MethodStructure} -import org.neo4j.cypher.internal.frontend.v3_0.symbols - -case class Or(lhs: CodeGenExpression, rhs: CodeGenExpression) extends CodeGenExpression with BinaryOperator { - - override def nullable(implicit context: CodeGenContext) = lhs.nullable || rhs.nullable - - override def cypherType(implicit context: CodeGenContext) = symbols.CTBoolean - - override protected def generator[E](structure: MethodStructure[E])(implicit context: CodeGenContext) = - if (!nullable && lhs.cypherType == symbols.CTBoolean && rhs.cypherType == symbols.CTBoolean) structure.or - else structure.threeValuedOr -} diff --git a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/Parameter.scala b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/Parameter.scala deleted file mode 100644 index ee3cbbf4bf6d5..0000000000000 --- a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/Parameter.scala +++ /dev/null @@ -1,36 +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.compiler.v3_0.codegen.ir.expressions - -import org.neo4j.cypher.internal.compiler.v3_0.codegen.{CodeGenContext, MethodStructure} -import org.neo4j.cypher.internal.frontend.v3_0.symbols._ - -case class Parameter(key: String, variableName: String) extends CodeGenExpression { - - override def init[E](generator: MethodStructure[E])(implicit context: CodeGenContext) = - generator.expectParameter(key, variableName) - - override def generateExpression[E](structure: MethodStructure[E])(implicit context: CodeGenContext): E = - structure.load(variableName) - - override def nullable(implicit context: CodeGenContext) = true - - override def cypherType(implicit context: CodeGenContext) = CTAny -} diff --git a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/RelationshipExpression.scala b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/RelationshipExpression.scala deleted file mode 100644 index fe6e8ecaa16b4..0000000000000 --- a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/RelationshipExpression.scala +++ /dev/null @@ -1,42 +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.compiler.v3_0.codegen.ir.expressions - -import org.neo4j.cypher.internal.compiler.v3_0.codegen.{CodeGenContext, MethodStructure, Variable} -import org.neo4j.cypher.internal.frontend.v3_0.symbols -import org.neo4j.cypher.internal.frontend.v3_0.symbols._ - -case class RelationshipExpression(relId: Variable) extends CodeGenExpression { - assert(relId.cypherType == symbols.CTRelationship) - - override def init[E](generator: MethodStructure[E])(implicit context: CodeGenContext) = {} - - override def generateExpression[E](structure: MethodStructure[E])(implicit context: CodeGenContext) = { - if (relId.nullable) - structure.nullable(relId.name, relId.cypherType, structure.relationship(relId.name)) - else - structure.relationship(relId.name) - - } - - override def nullable(implicit context: CodeGenContext) = relId.nullable - - override def cypherType(implicit context: CodeGenContext) = CTRelationship -} diff --git a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/RelationshipProjection.scala b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/RelationshipProjection.scala deleted file mode 100644 index 79fc2c7922a38..0000000000000 --- a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/RelationshipProjection.scala +++ /dev/null @@ -1,41 +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.compiler.v3_0.codegen.ir.expressions - -import org.neo4j.cypher.internal.compiler.v3_0.codegen.{Variable, CodeGenContext, MethodStructure} -import org.neo4j.cypher.internal.frontend.v3_0.symbols -import org.neo4j.cypher.internal.frontend.v3_0.symbols._ - -case class RelationshipProjection(relId: Variable) extends CodeGenExpression { - assert(relId.cypherType == symbols.CTRelationship) - - override def init[E](generator: MethodStructure[E])(implicit context: CodeGenContext) = {} - - override def generateExpression[E](structure: MethodStructure[E])(implicit context: CodeGenContext) ={ - if (relId.nullable) - structure.nullable(relId.name, relId.cypherType, structure.materializeRelationship(relId.name)) - else - structure.materializeRelationship(relId.name) - } - - override def nullable(implicit context: CodeGenContext) = relId.nullable - - override def cypherType(implicit context: CodeGenContext) = CTRelationship -} diff --git a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/Subtraction.scala b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/Subtraction.scala deleted file mode 100644 index 3ddc49e85e60f..0000000000000 --- a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/Subtraction.scala +++ /dev/null @@ -1,30 +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.compiler.v3_0.codegen.ir.expressions - -import org.neo4j.cypher.internal.compiler.v3_0.codegen.{CodeGenContext, MethodStructure} - -case class Subtraction(lhs: CodeGenExpression, rhs: CodeGenExpression) - extends CodeGenExpression with BinaryOperator with NumericalOpType { - - override protected def generator[E](structure: MethodStructure[E])(implicit context: CodeGenContext) = structure.sub - - override def nullable(implicit context: CodeGenContext) = lhs.nullable || rhs.nullable -} diff --git a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/ToSet.scala b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/ToSet.scala deleted file mode 100644 index 46ecd99b5ba67..0000000000000 --- a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/ToSet.scala +++ /dev/null @@ -1,35 +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.compiler.v3_0.codegen.ir.expressions - -import org.neo4j.cypher.internal.compiler.v3_0.codegen.{CodeGenContext, MethodStructure} -import org.neo4j.cypher.internal.frontend.v3_0.symbols._ - -case class ToSet(expression: CodeGenExpression) extends CodeGenExpression { - - override def init[E](generator: MethodStructure[E])(implicit context: CodeGenContext) = expression.init(generator) - - override def generateExpression[E](structure: MethodStructure[E])(implicit context: CodeGenContext) = - structure.toSet(expression.generateExpression(structure)) - - override def nullable(implicit context: CodeGenContext) = false - - override def cypherType(implicit context: CodeGenContext) = CTList(CTAny) -} diff --git a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/TypeOf.scala b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/TypeOf.scala deleted file mode 100644 index 9e1bcbb49230d..0000000000000 --- a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/TypeOf.scala +++ /dev/null @@ -1,48 +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.compiler.v3_0.codegen.ir.expressions - -import org.neo4j.cypher.internal.compiler.v3_0.codegen.{CodeGenContext, MethodStructure, Variable} -import org.neo4j.cypher.internal.frontend.v3_0.symbols.{CypherType, _} - -case class TypeOf(relId: Variable) - extends CodeGenExpression { - - def init[E](generator: MethodStructure[E])(implicit context: CodeGenContext) = {} - - def generateExpression[E](structure: MethodStructure[E])(implicit context: CodeGenContext) = { - val typeName = context.namer.newVarName() - structure.declare(typeName, CTString) - if (nullable) { - structure.ifStatement(structure.notNull(relId.name, relId.cypherType)) { body => - body.relType(relId.name, typeName) - } - structure.load(typeName) - } - else { - structure.relType(relId.name, typeName) - structure.load(typeName) - } - } - - override def nullable(implicit context: CodeGenContext) = relId.nullable - - override def cypherType(implicit context: CodeGenContext): CypherType = CTBoolean -} diff --git a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/functions/CodeGenFunction1.scala b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/functions/CodeGenFunction1.scala deleted file mode 100644 index 5ce4786274185..0000000000000 --- a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/functions/CodeGenFunction1.scala +++ /dev/null @@ -1,44 +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.compiler.v3_0.codegen.ir.functions - -import org.neo4j.cypher.internal.compiler.v3_0.codegen.ir.expressions._ -import org.neo4j.cypher.internal.frontend.v3_0.InternalException - -sealed trait CodeGenFunction1 extends ((CodeGenExpression) => CodeGenExpression) - -case object IdCodeGenFunction extends CodeGenFunction1 { - - override def apply(arg: CodeGenExpression): CodeGenExpression = arg match { - case n: NodeExpression => LoadVariable(n.nodeIdVar) - case n: NodeProjection => LoadVariable(n.nodeIdVar) - case r: RelationshipExpression => LoadVariable(r.relId) - case r: RelationshipProjection => LoadVariable(r.relId) - case e => throw new InternalException(s"id function only accepts nodes or relationships not $e") - } -} - -case object TypeCodeGenFunction extends CodeGenFunction1 { - override def apply(arg: CodeGenExpression): CodeGenExpression = arg match { - case r: RelationshipExpression => TypeOf(r.relId) - case r: RelationshipProjection => TypeOf(r.relId) - case e => throw new InternalException(s"type function only accepts relationships $e") - } -} diff --git a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/functions/functionConverter.scala b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/functions/functionConverter.scala deleted file mode 100644 index 3336de2283818..0000000000000 --- a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/functions/functionConverter.scala +++ /dev/null @@ -1,47 +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.compiler.v3_0.codegen.ir.functions - -import org.neo4j.cypher.internal.compiler.v3_0.codegen.CodeGenContext -import org.neo4j.cypher.internal.compiler.v3_0.codegen.ir.expressions._ -import org.neo4j.cypher.internal.compiler.v3_0.planner.CantCompileQueryException -import org.neo4j.cypher.internal.frontend.v3_0.ast - -object functionConverter { - - def apply(fcn: ast.FunctionInvocation, callback: ast.Expression => CodeGenExpression) - (implicit context: CodeGenContext): CodeGenExpression = fcn.function match { - - // id(n) - case Some(ast.functions.Id) => - assert(fcn.args.size == 1) - IdCodeGenFunction(callback(fcn.args(0))) - - // type(r) - case Some(ast.functions.Type) => - assert(fcn.args.size == 1) - TypeCodeGenFunction(callback(fcn.args(0))) - - case other => throw new CantCompileQueryException(s"Function $other not yet supported") - } -} - - - diff --git a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/executionplan/CompiledExecutionResult.scala b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/executionplan/CompiledExecutionResult.scala deleted file mode 100644 index 6a404c081181f..0000000000000 --- a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/executionplan/CompiledExecutionResult.scala +++ /dev/null @@ -1,65 +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.compiler.v3_0.executionplan - -import java.util - -import org.neo4j.cypher.internal.compiler.v3_0._ -import org.neo4j.cypher.internal.compiler.v3_0.planDescription.InternalPlanDescription -import org.neo4j.cypher.internal.compiler.v3_0.spi.{InternalResultVisitor, QueryContext} -import org.neo4j.cypher.internal.frontend.v3_0.ProfilerStatisticsNotReadyException - -trait SuccessfulCloseable { - def success(): Unit - def close(): Unit -} - -/** - * Main class for compiled execution results, implements everything in InternalExecutionResult - * except `javaColumns` and `accept` which delegates to the injected compiled code. - */ -class CompiledExecutionResult(taskCloser: TaskCloser, - context: QueryContext, - compiledCode: GeneratedQueryExecution, - description: Provider[InternalPlanDescription]) - extends StandardInternalExecutionResult(context, Some(taskCloser)) - with StandardInternalExecutionResult.IterateByAccepting { - - compiledCode.setSuccessfulCloseable(this) - - // *** Delegate to compiled code - def executionMode: ExecutionMode = compiledCode.executionMode() - - override def javaColumns: util.List[String] = compiledCode.javaColumns() - - override def accept[EX <: Exception](visitor: InternalResultVisitor[EX]): Unit = - compiledCode.accept(visitor) - - override def executionPlanDescription(): InternalPlanDescription = { - if (!taskCloser.isClosed) throw new ProfilerStatisticsNotReadyException - - compiledCode.executionPlanDescription() - } - - override def queryStatistics() = InternalQueryStatistics() - - //TODO delegate to compiled code once writes are being implemented - override def executionType = READ_ONLY -} diff --git a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/executionplan/ExecutionPlanBuilder.scala b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/executionplan/ExecutionPlanBuilder.scala index 25c746cd7a017..8fca823dd6751 100644 --- a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/executionplan/ExecutionPlanBuilder.scala +++ b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/executionplan/ExecutionPlanBuilder.scala @@ -21,13 +21,8 @@ package org.neo4j.cypher.internal.compiler.v3_0.executionplan import java.time.Clock -import org.neo4j.cypher.internal.compiler.v3_0.codegen.QueryExecutionTracer -import org.neo4j.cypher.internal.compiler.v3_0.codegen.profiling.ProfilingTracer -import org.neo4j.cypher.internal.compiler.v3_0.executionplan.ExecutionPlanBuilder.DescriptionProvider import org.neo4j.cypher.internal.compiler.v3_0.executionplan.builders._ import org.neo4j.cypher.internal.compiler.v3_0.pipes._ -import org.neo4j.cypher.internal.compiler.v3_0.planDescription.InternalPlanDescription -import org.neo4j.cypher.internal.compiler.v3_0.planDescription.InternalPlanDescription.Arguments import org.neo4j.cypher.internal.compiler.v3_0.planner.logical.plans.LogicalPlan import org.neo4j.cypher.internal.compiler.v3_0.planner.{CantCompileQueryException, CantHandleQueryException} import org.neo4j.cypher.internal.compiler.v3_0.profiler.Profiler @@ -38,23 +33,6 @@ import org.neo4j.cypher.internal.frontend.v3_0.ast.Statement import org.neo4j.cypher.internal.frontend.v3_0.notification.InternalNotification import org.neo4j.kernel.GraphDatabaseQueryService - -trait RunnablePlan { - def apply(queryContext: QueryContext, - execMode: ExecutionMode, - descriptionProvider: DescriptionProvider, - params: Map[String, Any], - closer: TaskCloser): InternalExecutionResult -} - -case class CompiledPlan(updating: Boolean, - periodicCommit: Option[PeriodicCommitInfo] = None, - fingerprint: Option[PlanFingerprint] = None, - plannerUsed: PlannerName, - planDescription: InternalPlanDescription, - columns: Seq[String], - executionResultBuilder: RunnablePlan ) - case class PipeInfo(pipe: Pipe, updating: Boolean, periodicCommit: Option[PeriodicCommitInfo] = None, @@ -164,27 +142,3 @@ object InterpretedExecutionPlanBuilder { builder.build(queryId, planType, params, notificationLogger) } } - -object ExecutionPlanBuilder { - type DescriptionProvider = - (InternalPlanDescription => (Provider[InternalPlanDescription], Option[QueryExecutionTracer])) - - def tracer( mode: ExecutionMode ) : DescriptionProvider = mode match { - case ProfileMode => - val tracer = new ProfilingTracer() - (description: InternalPlanDescription) => (new Provider[InternalPlanDescription] { - - override def get(): InternalPlanDescription = description.map { - plan: InternalPlanDescription => - val data = tracer.get(plan.id) - plan. - addArgument(Arguments.DbHits(data.dbHits())). - addArgument(Arguments.Rows(data.rows())). - addArgument(Arguments.Time(data.time())) - } - }, Some(tracer)) - case _ => (description: InternalPlanDescription) => (new Provider[InternalPlanDescription] { - override def get(): InternalPlanDescription = description - }, None) - } -} diff --git a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/setStaticField.scala b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/executionplan/SuccessfulCloseable.scala similarity index 80% rename from community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/setStaticField.scala rename to community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/executionplan/SuccessfulCloseable.scala index 128d050965588..cf69962c420bb 100644 --- a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/setStaticField.scala +++ b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/executionplan/SuccessfulCloseable.scala @@ -17,10 +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.compiler.v3_0.codegen +package org.neo4j.cypher.internal.compiler.v3_0.executionplan -object setStaticField { - def apply(clazz: Class[_], name: String, value: AnyRef) = { - clazz.getDeclaredField(name).set(null, value) - } +trait SuccessfulCloseable { + def success(): Unit + def close(): Unit } diff --git a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/executionplan/procs/ProcedureExecutionResult.scala b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/executionplan/procs/ProcedureExecutionResult.scala index c8a94ed36a2b5..d959994cde142 100644 --- a/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/executionplan/procs/ProcedureExecutionResult.scala +++ b/community/cypher/cypher-compiler-3.0/src/main/scala/org/neo4j/cypher/internal/compiler/v3_0/executionplan/procs/ProcedureExecutionResult.scala @@ -21,11 +21,10 @@ package org.neo4j.cypher.internal.compiler.v3_0.executionplan.procs import java.util -import org.neo4j.cypher.internal.compiler.v3_0.codegen.ResultRowImpl +import org.neo4j.cypher.internal.compiler.v3_0._ import org.neo4j.cypher.internal.compiler.v3_0.executionplan.{InternalQueryType, ProcedureCallMode, StandardInternalExecutionResult} import org.neo4j.cypher.internal.compiler.v3_0.planDescription.InternalPlanDescription -import org.neo4j.cypher.internal.compiler.v3_0.spi.{QualifiedProcedureName, InternalResultVisitor, QueryContext} -import org.neo4j.cypher.internal.compiler.v3_0.{ExecutionMode, InternalQueryStatistics, ProfileMode, TaskCloser} +import org.neo4j.cypher.internal.compiler.v3_0.spi.{InternalResultVisitor, QualifiedProcedureName, QueryContext} import org.neo4j.cypher.internal.frontend.v3_0.ProfilerStatisticsNotReadyException /** diff --git a/community/cypher/cypher-compiler-3.0/src/test/java/org/neo4j/cypher/internal/compiler/v3_0/codegen/SetStaticFieldTest.java b/community/cypher/cypher-compiler-3.0/src/test/java/org/neo4j/cypher/internal/compiler/v3_0/codegen/SetStaticFieldTest.java deleted file mode 100644 index 59d77b67cfbf0..0000000000000 --- a/community/cypher/cypher-compiler-3.0/src/test/java/org/neo4j/cypher/internal/compiler/v3_0/codegen/SetStaticFieldTest.java +++ /dev/null @@ -1,42 +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.compiler.v3_0.codegen; - -import org.junit.Test; - -import static org.junit.Assert.assertEquals; - -public class SetStaticFieldTest -{ - @Test - public void shouldAssignFields() - { - // when - setStaticField.apply( Apa.class, "X", "HELLO WORLD!" ); - - // then - assertEquals( Apa.X, "HELLO WORLD!" ); - } - - public static class Apa - { - public static String X; - } -} diff --git a/community/cypher/cypher-compiler-3.0/src/test/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ResultRowImplTest.scala b/community/cypher/cypher-compiler-3.0/src/test/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ResultRowImplTest.scala deleted file mode 100644 index 87a15f2a846ab..0000000000000 --- a/community/cypher/cypher-compiler-3.0/src/test/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ResultRowImplTest.scala +++ /dev/null @@ -1,30 +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.compiler.v3_0.codegen - -import org.neo4j.cypher.internal.frontend.v3_0.test_helpers.CypherFunSuite - -class ResultRowImplTest extends CypherFunSuite { - test("int can be handled as a Number") { - val row = new ResultRowImpl - row.set("x", 10) - row.getNumber("x") should equal(10) - } -} diff --git a/community/cypher/cypher-compiler-3.0/src/test/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/CodeGenExpressionTypesTest.scala b/community/cypher/cypher-compiler-3.0/src/test/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/CodeGenExpressionTypesTest.scala deleted file mode 100644 index b580de9d853ae..0000000000000 --- a/community/cypher/cypher-compiler-3.0/src/test/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/expressions/CodeGenExpressionTypesTest.scala +++ /dev/null @@ -1,62 +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.compiler.v3_0.codegen.ir.expressions - -import org.neo4j.cypher.internal.compiler.v3_0.codegen.{Variable, CodeGenContext} -import org.neo4j.cypher.internal.frontend.v3_0.symbols._ -import org.neo4j.cypher.internal.frontend.v3_0.test_helpers.CypherFunSuite - -class CodeGenExpressionTypesTest extends CypherFunSuite { - - val int = Literal(1: java.lang.Integer) - val double = Literal(1.1: java.lang.Double) - val string = Literal("apa") - val node = NodeProjection(Variable("a", CTNode)) - val rel = RelationshipProjection(Variable("a", CTRelationship)) - val intCollection = Collection(Seq(int)) - val doubleCollection = Collection(Seq(double)) - val stringCollection = Collection(Seq(string)) - val nodeCollection = Collection(Seq(node)) - val relCollection = Collection(Seq(rel)) - - test("collection") { - implicit val context: CodeGenContext = null - - Collection(Seq(int)).cypherType should equal(CTList(CTInteger)) - Collection(Seq(double)).cypherType should equal(CTList(CTFloat)) - Collection(Seq(int, double)).cypherType should equal(CTList(CTNumber)) - Collection(Seq(string, int)).cypherType should equal(CTList(CTAny)) - Collection(Seq(node, rel)).cypherType should equal(CTList(CTMap)) - } - - test("add") { - implicit val context: CodeGenContext = null - - Addition(int, double).cypherType should equal(CTFloat) - Addition(string, int).cypherType should equal(CTAny) - Addition(string, string).cypherType should equal(CTString) - Addition(intCollection, int).cypherType should equal(CTList(CTInteger)) - Addition(int, intCollection).cypherType should equal(CTList(CTInteger)) - Addition(double, intCollection).cypherType should equal(CTList(CTNumber)) - Addition(doubleCollection, intCollection).cypherType should equal(CTList(CTNumber)) - Addition(stringCollection, string).cypherType should equal(CTList(CTString)) - Addition(string, stringCollection).cypherType should equal(CTList(CTString)) - } -} diff --git a/community/cypher/cypher-compiler-3.0/src/test/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/profiling/ProfilingTracerTest.scala b/community/cypher/cypher-compiler-3.0/src/test/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/profiling/ProfilingTracerTest.scala deleted file mode 100644 index cc3de73c12c13..0000000000000 --- a/community/cypher/cypher-compiler-3.0/src/test/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/profiling/ProfilingTracerTest.scala +++ /dev/null @@ -1,104 +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.compiler.v3_0.codegen.profiling - -import org.neo4j.cypher.internal.compiler.v3_0.planDescription.Id -import org.neo4j.cypher.internal.frontend.v3_0.test_helpers.CypherFunSuite - -class ProfilingTracerTest extends CypherFunSuite { - - class Clock extends ProfilingTracer.Clock { - var nanoTime: Long = 0L - - def progress(nanos: Long) { - assert(nanos > 0, "time must move forwards") - nanoTime += nanos - } - } - - test("shouldReportExecutionTimeOfQueryExecution") { - // given - val clock = new Clock - val operatorId = new Id - val tracer = new ProfilingTracer(clock) - val event = tracer.executeOperator(operatorId) - - // when - clock.progress(516) - event.close() - - // then - tracer.timeOf(operatorId) should equal(516) - } - - test("multiple uses of the same Id should aggregate spent time") { - // given - val clock = new Clock - val operatorId = new Id - val tracer = new ProfilingTracer(clock) - - // when - val event1 = tracer.executeOperator(operatorId) - clock.progress(12) - event1.close() - - val event2 = tracer.executeOperator(operatorId) - clock.progress(45) - event2.close() - - // then - tracer.timeOf(operatorId) should equal(12 + 45) - } - - test("shouldReportDbHitsOfQueryExecution") { - // given - val operatorId = new Id - val tracer = new ProfilingTracer - val event = tracer.executeOperator(operatorId) - - // when - (0 until 516).foreach { _ => - event.dbHit() - } - - event.close() - - // then - tracer.dbHitsOf(operatorId) should equal(516) - } - - test("shouldReportRowsOfQueryExecution") { - // given - val operatorId = new Id - val tracer = new ProfilingTracer - val event = tracer.executeOperator(operatorId) - - // when - (0 until 516).foreach { _ => - event.row() - } - - event.close() - - // then - tracer.rowsOf(operatorId) should equal(516) - - } -} diff --git a/community/cypher/cypher-compiler-3.0/src/test/scala/org/neo4j/cypher/internal/compiler/v3_0/executionplan/CompiledExecutionResultTest.scala b/community/cypher/cypher-compiler-3.0/src/test/scala/org/neo4j/cypher/internal/compiler/v3_0/executionplan/CompiledExecutionResultTest.scala deleted file mode 100644 index f400da8b4a295..0000000000000 --- a/community/cypher/cypher-compiler-3.0/src/test/scala/org/neo4j/cypher/internal/compiler/v3_0/executionplan/CompiledExecutionResultTest.scala +++ /dev/null @@ -1,177 +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.compiler.v3_0.executionplan - -import java.util - -import org.mockito.Matchers._ -import org.mockito.Mockito._ -import org.neo4j.cypher.internal.compiler.v3_0.codegen.ResultRowImpl -import org.neo4j.cypher.internal.compiler.v3_0.planDescription.InternalPlanDescription -import org.neo4j.cypher.internal.compiler.v3_0.spi.{InternalResultRow, InternalResultVisitor, QueryContext} -import org.neo4j.cypher.internal.compiler.v3_0.{ExecutionMode, NormalMode, TaskCloser} -import org.neo4j.cypher.internal.frontend.v3_0.test_helpers.CypherFunSuite -import org.neo4j.helpers.collection.Iterators - -import scala.collection.JavaConverters._ - -class CompiledExecutionResultTest extends CypherFunSuite { - - test("should return scala objects") { - val result = newCompiledExecutionResult(javaMap("foo" -> "", "bar" -> "")) - - result.columns should equal(List("foo", "bar")) - } - - test("should return scala objects for string") { - val result = newCompiledExecutionResult(javaMap("foo" -> "bar")) - - result.columnAs[String]("foo").toList should equal(List("bar")) - } - - test("should return scala objects for list") { - val result = newCompiledExecutionResult(javaMap("foo" -> javaList(42))) - - result.columnAs[List[Integer]]("foo").toList should equal(List(List(42))) - } - - test("should return scala objects for map") { - val result = newCompiledExecutionResult(javaMap("foo" -> javaMap("key" -> "value"))) - - result.columnAs[Map[String, Any]]("foo").toList should equal(List(Map("key" -> "value"))) - } - - test("should return java objects for string") { - val result = newCompiledExecutionResult(javaMap("foo" -> "bar")) - - Iterators.asList(result.javaColumnAs[String]("foo")) should equal(javaList("bar")) - } - - test("should return java objects for list") { - val result = newCompiledExecutionResult(javaMap("foo" -> javaList(42))) - - Iterators.asList(result.javaColumnAs[List[Integer]]("foo")) should equal(javaList(javaList(42))) - } - - test("should return java objects for map") { - val result = newCompiledExecutionResult(javaMap("foo" -> javaMap("key" -> "value"))) - - Iterators.asList(result.javaColumnAs[Map[String, Any]]("foo")) should equal(javaList(javaMap("key" -> "value"))) - } - - test("result should be a scala iterator for string") { - val result = newCompiledExecutionResult(javaMap("foo" -> "bar")) - - result.toList should equal(List(Map("foo" -> "bar"))) - } - - test("result should be a scala iterator for list") { - val result = newCompiledExecutionResult(javaMap("foo" -> javaList(42))) - - result.toList should equal(List(Map("foo" -> List(42)))) - } - - test("result should be a scala iterator for map") { - val result = newCompiledExecutionResult(javaMap("foo" -> javaMap("key" -> "value"))) - - result.toList should equal(List(Map("foo" -> Map("key" -> "value")))) - } - - test("should return a java iterator for string") { - val result = newCompiledExecutionResult(javaMap("foo" -> "bar")) - - Iterators.asList(result.javaIterator) should equal(javaList(javaMap("foo" -> "bar"))) - } - - test("should return a java iterator for list") { - val result = newCompiledExecutionResult(javaMap("foo" -> javaList(42))) - - Iterators.asList(result.javaIterator) should equal(javaList(javaMap("foo" -> javaList(42)))) - } - - test("should return a java iterator for map") { - val result = newCompiledExecutionResult(javaMap("foo" -> javaMap("key" -> "value"))) - - Iterators.asList(result.javaIterator) should equal(javaList(javaMap("foo" -> javaMap("key" -> "value")))) - } - - test("javaIterator hasNext should not call accept if results already consumed") { - // given - var timesCalled = 0 - val result = newCompiledExecutionResult(assertion = () => { - // then - timesCalled should equal(0) - timesCalled += 1 - }) - - // when - result.accept(new InternalResultVisitor[Exception] { - override def visit(row: InternalResultRow): Boolean = { - false - } - }) - } - - test("close should work after result is consumed") { - // given - val result = newCompiledExecutionResult(javaMap("a" -> "1", "b" -> "2")) - - // when - result.accept(new InternalResultVisitor[Exception] { - override def visit(row: InternalResultRow): Boolean = { - true - } - }) - - result.close() - - // then - // call of close actually worked - } - - private def newCompiledExecutionResult(row: util.Map[String, Any] = new util.HashMap(), - taskCloser: TaskCloser = new TaskCloser, - assertion: () => Unit = () => {}) = { - val noCompiledCode: GeneratedQueryExecution = new GeneratedQueryExecution { - override def setSuccessfulCloseable(closeable: SuccessfulCloseable){} - override def javaColumns(): util.List[String] = new util.ArrayList(row.keySet()) - override def executionMode(): ExecutionMode = NormalMode - override def accept[E <: Exception](visitor: InternalResultVisitor[E]): Unit = { - try { - val rowImpl = new ResultRowImpl() - row.asScala.foreach { case (k, v) => rowImpl.set(k, v) } - visitor.visit(rowImpl) - assertion() - } finally { - taskCloser.close(success = true) - } - } - override def executionPlanDescription(): InternalPlanDescription = ??? - } - - val context = mock[QueryContext] - when(context.isGraphKernelResultValue(any())).thenReturn(false) - new CompiledExecutionResult(taskCloser, context, noCompiledCode, null) - } - - private def javaList[T](elements: T*): util.List[T] = elements.toList.asJava - - private def javaMap[K, V](pairs: (K, V)*): util.Map[K, V] = pairs.toMap.asJava -} diff --git a/community/cypher/cypher/src/main/java/org/neo4j/cypher/internal/codegen/CompiledConversionUtils.java b/community/cypher/cypher/src/main/java/org/neo4j/cypher/internal/codegen/CompiledConversionUtils.java deleted file mode 100644 index 31240becc52fa..0000000000000 --- a/community/cypher/cypher/src/main/java/org/neo4j/cypher/internal/codegen/CompiledConversionUtils.java +++ /dev/null @@ -1,206 +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.codegen; - -import org.neo4j.cypher.internal.frontend.v3_0.CypherTypeException; -import org.neo4j.cypher.internal.frontend.v3_0.IncomparableValuesException; -import org.neo4j.graphdb.Node; -import org.neo4j.graphdb.Relationship; -import org.neo4j.helpers.MathUtil; - -import java.lang.reflect.Array; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; - -// Class with static methods used by compiled execution plans -public abstract class CompiledConversionUtils -{ - public static boolean coerceToPredicate( Object value ) - { - if ( value == null ) - { - return false; - } - if ( value instanceof Boolean ) - { - return (boolean) value; - } - if ( value.getClass().isArray() ) - { - return Array.getLength( value ) > 0; - } - throw new CypherTypeException( "Don't know how to treat that as a predicate: " + value.toString(), null ); - } - - public static Collection toCollection( Object value ) - { - if ( value == null ) - { - return Collections.emptyList(); - } - if ( value instanceof Collection ) - { - return ((Collection) value); - } - - throw new CypherTypeException( "Don't know how to create an iterable out of " + value.getClass().getSimpleName(), null ); - } - - public static CompositeKey compositeKey( long... keys ) - { - return new CompositeKey( keys ); - } - - public static class CompositeKey - { - private final long[] key; - - private CompositeKey( long[] key ) - { - this.key = key; - } - - @Override - public boolean equals( Object o ) - { - if ( this == o ) - { return true; } - if ( o == null || getClass() != o.getClass() ) - { return false; } - - CompositeKey that = (CompositeKey) o; - - return Arrays.equals( key, that.key ); - - } - - @Override - public int hashCode() - { - return Arrays.hashCode( key ); - } - } - - public static Boolean equals( Object lhs, Object rhs ) - { - if ( lhs == null || rhs == null ) - { - return null; - } - - if ( (lhs instanceof NodeIdWrapper && !(rhs instanceof NodeIdWrapper)) || - (rhs instanceof NodeIdWrapper && !(lhs instanceof NodeIdWrapper)) || - (lhs instanceof RelationshipIdWrapper && !(rhs instanceof RelationshipIdWrapper)) || - (rhs instanceof RelationshipIdWrapper && !(lhs instanceof RelationshipIdWrapper)) ) - { - - throw new IncomparableValuesException( lhs.getClass().getSimpleName(), rhs.getClass().getSimpleName() ); - } - - //if floats compare float values if integer types, - //compare long values - if ( lhs instanceof Number && rhs instanceof Number ) - { - if ( (lhs instanceof Double || lhs instanceof Float) - && (rhs instanceof Double || rhs instanceof Float) ) - { - double left = ((Number) lhs).doubleValue(); - double right = ((Number) rhs).doubleValue(); - return left == right; - } - else if ( (lhs instanceof Double || lhs instanceof Float) ) - { - double left = ((Number) lhs).doubleValue(); - long right = ((Number) rhs).longValue(); - return MathUtil.numbersEqual( left, right ); - } - else if ( (rhs instanceof Double || rhs instanceof Float) ) - { - long left = ((Number) lhs).longValue(); - double right = ((Number) rhs).doubleValue(); - return MathUtil.numbersEqual( right, left ); - } - - //evertyhing else is long from cyphers point-of-view - long left = ((Number) lhs).longValue(); - long right = ((Number) rhs).longValue(); - return left == right; - } - - //for everything else call equals - return lhs.equals( rhs ); - } - - public static Boolean or( Object lhs, Object rhs ) - { - if ( lhs == null && rhs == null ) - { - return null; - } - else if ( lhs == null && rhs instanceof Boolean ) - { - return (Boolean) rhs ? true : null; - } - else if ( rhs == null && lhs instanceof Boolean ) - { - return (Boolean) lhs ? true : null; - } - else if ( lhs instanceof Boolean && rhs instanceof Boolean ) - { - return (Boolean) lhs || (Boolean) rhs; - } - - throw new CypherTypeException( - "Don't know how to do or on: " + (lhs != null ? lhs.toString() : null) + " and " + - (rhs != null ? rhs.toString() : null), null ); - } - - public static Boolean not( Object predicate ) - { - if ( predicate == null ) - { - return null; - } - - if ( predicate instanceof Boolean ) - { - return !(Boolean) predicate; - } - - throw new CypherTypeException( "Don't know how to treat that as a boolean: " + predicate.toString(), null ); - } - - public static Object loadParameter( Object value ) - { - if ( value instanceof Node ) - { - return new NodeIdWrapper( ((Node) value).getId() ); - } - else if ( value instanceof Relationship ) - { - return new RelationshipIdWrapper( ((Relationship) value).getId() ); - } - else - { - return value; - } - } -} diff --git a/community/cypher/cypher/src/main/java/org/neo4j/cypher/internal/codegen/CompiledExpandUtils.java b/community/cypher/cypher/src/main/java/org/neo4j/cypher/internal/codegen/CompiledExpandUtils.java deleted file mode 100644 index b7eb02a65964c..0000000000000 --- a/community/cypher/cypher/src/main/java/org/neo4j/cypher/internal/codegen/CompiledExpandUtils.java +++ /dev/null @@ -1,150 +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.codegen; - -import org.neo4j.graphdb.Direction; -import org.neo4j.kernel.api.ReadOperations; -import org.neo4j.kernel.api.exceptions.EntityNotFoundException; -import org.neo4j.kernel.impl.api.RelationshipDataExtractor; -import org.neo4j.kernel.impl.api.RelationshipVisitor; -import org.neo4j.kernel.impl.api.store.RelationshipIterator; - -//TODO this must live outside 2.3 -public abstract class CompiledExpandUtils -{ - public static RelationshipIterator connectingRelationships( ReadOperations readOperations, - long fromNode, Direction direction, long toNode ) throws EntityNotFoundException - { - int fromDegree = readOperations.nodeGetDegree( fromNode, direction ); - if ( fromDegree == 0 ) - { - return RelationshipIterator.EMPTY; - } - - int toDegree = readOperations.nodeGetDegree( toNode, direction.reverse() ); - if ( toDegree == 0 ) - { - return RelationshipIterator.EMPTY; - } - - long startNode; - long endNode; - Direction relDirection; - if ( fromDegree < toDegree ) - { - startNode = fromNode; - endNode = toNode; - relDirection = direction; - } - else - { - startNode = toNode; - endNode = fromNode; - relDirection = direction.reverse(); - } - - RelationshipIterator allRelationships = readOperations.nodeGetRelationships( startNode, relDirection ); - - return connectingRelationshipsIterator( allRelationships, startNode, endNode ); - } - - - public static RelationshipIterator connectingRelationships( ReadOperations readOperations, - long fromNode, Direction direction, long toNode, int... relTypes ) throws EntityNotFoundException - { - int fromDegree = calculateTotalDegree( readOperations, fromNode, direction, relTypes); - if ( fromDegree == 0 ) - { - return RelationshipIterator.EMPTY; - } - - int toDegree = calculateTotalDegree( readOperations, toNode, direction.reverse(), relTypes ); - if ( toDegree == 0 ) - { - return RelationshipIterator.EMPTY; - } - - long startNode; - long endNode; - Direction relDirection; - if ( fromDegree < toDegree ) - { - startNode = fromNode; - endNode = toNode; - relDirection = direction; - } - else - { - startNode = toNode; - endNode = fromNode; - relDirection = direction.reverse(); - } - - RelationshipIterator allRelationships = readOperations.nodeGetRelationships( startNode, relDirection, relTypes ); - - return connectingRelationshipsIterator( allRelationships, startNode, endNode ); - } - - private static int calculateTotalDegree( ReadOperations readOperations, long fromNode, Direction direction, - int[] relTypes ) throws EntityNotFoundException - { - int degree = 0; - for ( int relType : relTypes ) - { - degree += readOperations.nodeGetDegree( fromNode, direction, relType ); - } - - return degree; - } - - private static RelationshipIterator connectingRelationshipsIterator( final RelationshipIterator allRelationships, - final long fromNode, final long toNode ) - { - return new RelationshipIterator.BaseIterator() - { - private final RelationshipDataExtractor extractor = new RelationshipDataExtractor(); - - @Override - public boolean relationshipVisit( long relationshipId, - RelationshipVisitor visitor ) throws EXCEPTION - { - visitor.visit( extractor.relationship(), extractor.type(), extractor.startNode(), extractor.endNode() ); - return false; - } - - @Override - protected boolean fetchNext() - { - while ( allRelationships.hasNext() ) - { - allRelationships.relationshipVisit( allRelationships.next(), extractor ); - if ( extractor.otherNode( fromNode ) == toNode ) - { - next = extractor.relationship(); - return true; - } - } - - return false; - } - }; - } - -} diff --git a/community/cypher/cypher/src/main/java/org/neo4j/cypher/internal/codegen/CompiledMathHelper.java b/community/cypher/cypher/src/main/java/org/neo4j/cypher/internal/codegen/CompiledMathHelper.java deleted file mode 100644 index 91f8abc1359b1..0000000000000 --- a/community/cypher/cypher/src/main/java/org/neo4j/cypher/internal/codegen/CompiledMathHelper.java +++ /dev/null @@ -1,321 +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.codegen; - -import org.neo4j.cypher.internal.frontend.v3_0.ArithmeticException; -import org.neo4j.cypher.internal.frontend.v3_0.CypherTypeException; - -import java.lang.reflect.Array; -import java.util.ArrayList; -import java.util.List; - -/** - * This is a helper class used by compiled plans for doing basic math operations - */ -public final class CompiledMathHelper -{ - private static final double EPSILON = Math.pow( 1, -10 ); - - /** - * Do not instantiate this class - */ - private CompiledMathHelper() - { - } - - /** - * Utility function for doing addition - */ - public static Object add( Object lhs, Object rhs ) - { - if ( lhs == null || rhs == null ) - { - return null; - } - - if ( lhs instanceof String || rhs instanceof String ) - { - return String.valueOf( lhs ) + String.valueOf( rhs ); - } - - //List addition - if ( lhs instanceof List && rhs instanceof List ) - { - List lhsList = (List) lhs; - List rhsList = (List) rhs; - List result = new ArrayList<>( lhsList.size() + rhsList.size() ); - result.addAll( lhsList ); - result.addAll( rhsList ); - return result; - } - else if ( lhs instanceof List ) - { - List lhsList = (List) lhs; - List result = new ArrayList<>( lhsList.size() + 1 ); - result.addAll( lhsList ); - result.add( rhs ); - return result; - } - else if ( rhs instanceof List ) - { - List rhsList = (List) rhs; - List result = new ArrayList<>( rhsList.size() + 1 ); - result.add( lhs ); - result.addAll( rhsList ); - return result; - } - - // array addition - Class lhsClass = lhs.getClass(); - Class rhsClass = rhs.getClass(); - if ( lhsClass.isArray() && rhsClass.isArray() ) - { - return addArrays( lhs, rhs ); - } - else if ( lhsClass.isArray() ) - { - return addArrayWithObject( lhs, rhs ); - } - else if ( rhsClass.isArray() ) - { - return addObjectWithArray( lhs, rhs ); - } - - if ( lhs instanceof Number && rhs instanceof Number ) - { - if ( lhs instanceof Double || rhs instanceof Double || - lhs instanceof Float || rhs instanceof Float ) - { - return ((Number) lhs).doubleValue() + ((Number) rhs).doubleValue(); - } - if ( lhs instanceof Long || rhs instanceof Long || - lhs instanceof Integer || rhs instanceof Integer || - lhs instanceof Short || rhs instanceof Short || - lhs instanceof Byte || rhs instanceof Byte ) - { - try - { - return Math.addExact( ((Number) lhs).longValue(), ((Number) rhs).longValue() ); - } - catch ( java.lang.ArithmeticException e ) - { - throw new ArithmeticException( - String.format( "result of %d + %d cannot be represented as an integer", - ((Number) lhs).longValue(), ((Number) rhs).longValue() ), e); - } - } - // other numbers we cannot add - } - - throw new CypherTypeException( "Cannot add " + lhs.getClass().getSimpleName() + - " and " + rhs.getClass().getSimpleName(), null ); - } - - public static Object subtract( Object lhs, Object rhs ) - { - if ( lhs == null || rhs == null ) - { - return null; - } - - if ( lhs instanceof Number && rhs instanceof Number ) - { - if ( lhs instanceof Double || rhs instanceof Double || - lhs instanceof Float || rhs instanceof Float ) - { - return ((Number) lhs).doubleValue() - ((Number) rhs).doubleValue(); - } - if ( lhs instanceof Long || rhs instanceof Long || - lhs instanceof Integer || rhs instanceof Integer || - lhs instanceof Short || rhs instanceof Short || - lhs instanceof Byte || rhs instanceof Byte ) - { - try - { - return Math.subtractExact( ((Number) lhs).longValue(), ((Number) rhs).longValue() ); - } - catch ( java.lang.ArithmeticException e ) - { - throw new ArithmeticException( - String.format( "result of %d - %d cannot be represented as an integer", - ((Number) lhs).longValue(), ((Number) rhs).longValue() ), e); - } - } - // other numbers we cannot subtract - } - - throw new CypherTypeException( "Cannot add " + lhs.getClass().getSimpleName() + - " and " + rhs.getClass().getSimpleName(), null ); - } - - public static Object multiply( Object lhs, Object rhs ) - { - if ( lhs == null || rhs == null ) - { - return null; - } - - if ( lhs instanceof Number && rhs instanceof Number ) - { - if ( lhs instanceof Double || rhs instanceof Double || - lhs instanceof Float || rhs instanceof Float ) - { - return ((Number) lhs).doubleValue() * ((Number) rhs).doubleValue(); - } - if ( lhs instanceof Long || rhs instanceof Long || - lhs instanceof Integer || rhs instanceof Integer || - lhs instanceof Short || rhs instanceof Short || - lhs instanceof Byte || rhs instanceof Byte ) - { - return ((Number) lhs).longValue() * ((Number) rhs).longValue(); - } - // other numbers we cannot multiply - } - - throw new CypherTypeException( "Cannot multiply " + lhs.getClass().getSimpleName() + - " and " + rhs.getClass().getSimpleName(), null ); - } - - public static Object divide( Object lhs, Object rhs ) - { - if ( lhs == null || rhs == null ) - { - return null; - } - - if ( lhs instanceof Number && rhs instanceof Number ) - { - if ( lhs instanceof Double || rhs instanceof Double || - lhs instanceof Float || rhs instanceof Float ) - { - double left = ((Number) lhs).doubleValue(); - double right = ((Number) rhs).doubleValue(); - if ( Math.abs( right ) < EPSILON ) - { - throw new ArithmeticException( "/ by zero", null ); - } - return left / right; - } - if ( lhs instanceof Long || rhs instanceof Long || - lhs instanceof Integer || rhs instanceof Integer || - lhs instanceof Short || rhs instanceof Short || - lhs instanceof Byte || rhs instanceof Byte ) - { - long left = ((Number) lhs).longValue(); - long right = ((Number) rhs).longValue(); - if ( right == 0 ) - { - throw new ArithmeticException( "/ by zero", null ); - } - return left / right; - } - // other numbers we cannot divide - } - - throw new CypherTypeException( "Cannot divide " + lhs.getClass().getSimpleName() + - " and " + rhs.getClass().getSimpleName(), null ); - } - - public static Object modulo( Object lhs, Object rhs ) - { - if ( lhs == null || rhs == null ) - { - return null; - } - - if ( lhs instanceof Number && rhs instanceof Number ) - { - return ((Number) lhs).doubleValue() % ((Number) rhs).doubleValue(); - } - - throw new CypherTypeException( "Cannot modulo " + lhs.getClass().getSimpleName() + - " and " + rhs.getClass().getSimpleName(), null ); - } - - public static int transformToInt( Object value ) - { - if ( value == null ) - { - throw new CypherTypeException( "Expected a numeric value but got null", null ); - } - if ( value instanceof Number ) - { - Number number = (Number) value; - if ( number.longValue() > Integer.MAX_VALUE ) - { - throw new CypherTypeException( value.toString() + " is too large to cast to an int32", null ); - } - return number.intValue(); - } - throw new CypherTypeException( String.format( "Expected a numeric value but got %s", value.toString() ), null ); - } - - /** - * Both a1 and a2 must be arrays - */ - private static Object addArrays( Object a1, Object a2 ) - { - int l1 = Array.getLength( a1 ); - int l2 = Array.getLength( a2 ); - Object[] ret = new Object[l1 + l2]; - for ( int i = 0; i < l1; i++ ) - { - ret[i] = Array.get( a1, i ); - } - for ( int i = 0; i < l2; i++ ) - { - ret[l1 + i] = Array.get( a2, i ); - } - return ret; - } - - /** - * array must be an array - */ - private static Object addArrayWithObject( Object array, Object object ) - { - int l = Array.getLength( array ); - Object[] ret = new Object[l + 1]; - int i = 0; - for (; i < l; i++ ) - { - ret[i] = Array.get( array, i ); - } - ret[i] = object; - - return ret; - } - - /** - * array must be an array - */ - private static Object addObjectWithArray( Object object, Object array ) - { - int l = Array.getLength( array ); - Object[] ret = new Object[l + 1]; - ret[0] = object; - for ( int i = 1; i < ret.length; i++ ) - { - ret[i] = Array.get( array, i ); - } - - return ret; - } -} diff --git a/community/cypher/cypher/src/main/java/org/neo4j/cypher/internal/codegen/NodeIdWrapper.java b/community/cypher/cypher/src/main/java/org/neo4j/cypher/internal/codegen/NodeIdWrapper.java deleted file mode 100644 index d95043655d36c..0000000000000 --- a/community/cypher/cypher/src/main/java/org/neo4j/cypher/internal/codegen/NodeIdWrapper.java +++ /dev/null @@ -1,55 +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.codegen; - -public final class NodeIdWrapper -{ - private final long id; - - public NodeIdWrapper( long id ) - { - this.id = id; - } - - public long id() - { - return id; - } - - @Override - public boolean equals( Object o ) - { - if ( this == o ) - { return true; } - if ( o == null || getClass() != o.getClass() ) - { return false; } - - NodeIdWrapper that = (NodeIdWrapper) o; - - return id == that.id; - - } - - @Override - public int hashCode() - { - return (int) (id ^ (id >>> 32)); - } -} diff --git a/community/cypher/cypher/src/main/java/org/neo4j/cypher/internal/codegen/RelationshipIdWrapper.java b/community/cypher/cypher/src/main/java/org/neo4j/cypher/internal/codegen/RelationshipIdWrapper.java deleted file mode 100644 index f2c5fc85987aa..0000000000000 --- a/community/cypher/cypher/src/main/java/org/neo4j/cypher/internal/codegen/RelationshipIdWrapper.java +++ /dev/null @@ -1,55 +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.codegen; - -public final class RelationshipIdWrapper -{ - private final long id; - - public RelationshipIdWrapper( long id ) - { - this.id = id; - } - - public long id() - { - return id; - } - - @Override - public boolean equals( Object o ) - { - if ( this == o ) - { return true; } - if ( o == null || getClass() != o.getClass() ) - { return false; } - - RelationshipIdWrapper that = (RelationshipIdWrapper) o; - - return id == that.id; - - } - - @Override - public int hashCode() - { - return (int) (id ^ (id >>> 32)); - } -} diff --git a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/CypherRuntime.scala b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/CypherRuntime.scala index dbe7be287e49a..147d9a04f53dc 100644 --- a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/CypherRuntime.scala +++ b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/CypherRuntime.scala @@ -25,7 +25,6 @@ case object CypherRuntime extends CypherOptionCompanion[CypherRuntime] { case object default extends CypherRuntime("default") case object interpreted extends CypherRuntime("interpreted") - case object compiled extends CypherRuntime("compiled") - val all: Set[CypherRuntime] = Set(interpreted, compiled) + val all: Set[CypherRuntime] = Set(interpreted) } 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 fa7e9c4f0034c..0c41f4a7001c8 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 @@ -24,7 +24,7 @@ import java.time.Clock import org.neo4j.cypher.internal.compatibility.exceptionHandlerFor3_0 import org.neo4j.cypher.internal.compiler.v3_0._ import org.neo4j.cypher.internal.frontend.v3_0.InputPosition -import org.neo4j.cypher.{InvalidArgumentException, SyntaxException, _} +import org.neo4j.cypher.{SyntaxException, _} import org.neo4j.graphdb.factory.GraphDatabaseSettings import org.neo4j.kernel.GraphDatabaseQueryService import org.neo4j.kernel.api.KernelAPI @@ -91,9 +91,6 @@ class CypherCompiler(graph: GraphDatabaseQueryService, private val factory = new PlannerFactory(graph, kernelAPI, kernelMonitors, log, config) private val planners: PlannerCache = new PlannerCache(factory) - - private final val ILLEGAL_PLANNER_RUNTIME_COMBINATIONS: Set[(CypherPlanner, CypherRuntime)] = Set((CypherPlanner.rule, CypherRuntime.compiled)) - @throws(classOf[SyntaxException]) def preParseQuery(queryText: String): PreParsedQuery = exceptionHandlerFor3_0.runSafely{ val preParsedStatement = CypherPreParser(queryText) @@ -107,8 +104,6 @@ class CypherCompiler(graph: GraphDatabaseQueryService, val pickedRuntime = pick(runtime, CypherRuntime, if (cypherVersion == configuredVersion) Some(configuredRuntime) else None) val pickedUpdateStrategy = pick(updateStrategy, CypherUpdateStrategy, None) - assertValidOptions(CypherStatementWithOptions(preParsedStatement), cypherVersion, pickedExecutionMode, pickedPlanner, pickedRuntime) - PreParsedQuery(statement, queryText, cypherVersion, pickedExecutionMode, pickedPlanner, pickedRuntime, pickedUpdateStrategy)(offset) } @@ -118,12 +113,6 @@ class CypherCompiler(graph: GraphDatabaseQueryService, if (specified == companion.default) configured.getOrElse(specified) else specified } - private def assertValidOptions(statementWithOption: CypherStatementWithOptions, - cypherVersion: CypherVersion, executionMode: CypherExecutionMode, - planner: CypherPlanner, runtime: CypherRuntime) { - if (ILLEGAL_PLANNER_RUNTIME_COMBINATIONS((planner, runtime))) - throw new InvalidArgumentException(s"Unsupported PLANNER - RUNTIME combination: ${planner.name} - ${runtime.name}") - } @throws(classOf[SyntaxException]) def parseQuery(preParsedQuery: PreParsedQuery, tracer: CompilationPhaseTracer): ParsedQuery = { diff --git a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/CypherPreParser.scala b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/CypherPreParser.scala index b27dffbc58cd3..e6a09954f76f9 100644 --- a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/CypherPreParser.scala +++ b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/CypherPreParser.scala @@ -54,7 +54,6 @@ case object CypherPreParser extends Parser with Base { def RuntimeOption = rule("runtime option")( option("runtime", "interpreted") ~ push(InterpretedRuntimeOption) - | option("runtime", "compiled") ~ push(CompiledRuntimeOption) ) def StrategyOption = rule("strategy option")( diff --git a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/PreParserOption.scala b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/PreParserOption.scala index a35c9077c3844..03dd45883130e 100644 --- a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/PreParserOption.scala +++ b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/PreParserOption.scala @@ -34,7 +34,6 @@ case object GreedyPlannerOption extends PlannerPreParserOption("greedy") case object IDPPlannerOption extends PlannerPreParserOption("idp") case object DPPlannerOption extends PlannerPreParserOption("dp") case object InterpretedRuntimeOption extends RuntimePreParserOption("interpreted") -case object CompiledRuntimeOption extends RuntimePreParserOption("compiled") case object EagerOption extends UpdateStrategyOption("eager") case class ConfigurationOptions(version: Option[VersionOption], options: Seq[PreParserOption]) extends PreParserOption 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 3c9b502ee7954..abfba0419df65 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 @@ -444,7 +444,6 @@ case class CompatibilityFor2_3Cost(graph: GraphDatabaseQueryService, val runtimeName: Option[RuntimeName] = runtime match { case CypherRuntime.default => None case CypherRuntime.interpreted => Some(InterpretedRuntimeName) - case CypherRuntime.compiled => throw new IllegalArgumentException("Compiled runtime is not supported in Cypher 2.3") } val nodeManager = graph.getDependencyResolver.resolveDependency(classOf[NodeManager]) 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_0.scala index ab2d2e41d0485..7b03794f68395 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_0.scala @@ -527,7 +527,6 @@ case class CompatibilityFor3_0Cost(graph: GraphDatabaseQueryService, val runtimeName = runtime match { case CypherRuntime.default => None case CypherRuntime.interpreted => Some(InterpretedRuntimeName) - case CypherRuntime.compiled => Some(CompiledRuntimeName) } val updateStrategy = strategy match { case CypherUpdateStrategy.eager => Some(eagerUpdateStrategy) @@ -536,7 +535,7 @@ case class CompatibilityFor3_0Cost(graph: GraphDatabaseQueryService, val logger = new StringInfoLogger3_0(log) val monitors = new WrappedMonitors3_0(kernelMonitors) - CypherCompilerFactory.costBasedCompiler(graph, config, clock, GeneratedQueryStructure, + CypherCompilerFactory.costBasedCompiler(graph, config, clock, monitors, logger, rewriterSequencer, plannerName, runtimeName, updateStrategy, helpersv3_0.asPublicType) } diff --git a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_0/GeneratedQueryStructure.scala b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_0/GeneratedQueryStructure.scala deleted file mode 100644 index 30d57a06de961..0000000000000 --- a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v3_0/GeneratedQueryStructure.scala +++ /dev/null @@ -1,917 +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.spi.v3_0 - -import java.util - -import org.neo4j.codegen -import org.neo4j.codegen.CodeGeneratorOption._ -import org.neo4j.codegen.ExpressionTemplate._ -import org.neo4j.codegen.MethodReference._ -import org.neo4j.codegen.TypeReference._ -import org.neo4j.codegen._ -import org.neo4j.codegen.source.SourceVisitor -import org.neo4j.collection.primitive.hopscotch.LongKeyIntValueTable -import org.neo4j.collection.primitive.{Primitive, PrimitiveLongIntMap, PrimitiveLongIterator, PrimitiveLongObjectMap} -import org.neo4j.cypher.internal.codegen.CompiledConversionUtils.CompositeKey -import org.neo4j.cypher.internal.codegen.{CompiledConversionUtils, CompiledExpandUtils, CompiledMathHelper, NodeIdWrapper, RelationshipIdWrapper} -import org.neo4j.cypher.internal.compiler.v3_0.ast.convert.commands.DirectionConverter -import org.neo4j.cypher.internal.compiler.v3_0.codegen._ -import org.neo4j.cypher.internal.compiler.v3_0.executionplan._ -import org.neo4j.cypher.internal.compiler.v3_0.helpers._ -import org.neo4j.cypher.internal.compiler.v3_0.planDescription.{Id, InternalPlanDescription} -import org.neo4j.cypher.internal.compiler.v3_0.planner.CantCompileQueryException -import org.neo4j.cypher.internal.compiler.v3_0.spi.{InternalResultVisitor, QueryContext, QueryTransactionalContext} -import org.neo4j.cypher.internal.compiler.v3_0.{ExecutionMode, TaskCloser} -import org.neo4j.cypher.internal.frontend.v3_0.symbols.CypherType -import org.neo4j.cypher.internal.frontend.v3_0.{CypherExecutionException, ParameterNotFoundException, SemanticDirection, symbols} -import org.neo4j.graphdb.Result.{ResultRow, ResultVisitor} -import org.neo4j.graphdb.{Direction, Node, Relationship} -import org.neo4j.helpers.collection.MapUtil -import org.neo4j.kernel.api.exceptions.KernelException -import org.neo4j.kernel.api.index.IndexDescriptor -import org.neo4j.kernel.api.{ReadOperations, StatementTokenNameLookup, TokenNameLookup} -import org.neo4j.kernel.impl.api.store.RelationshipIterator -import org.neo4j.kernel.impl.api.{RelationshipDataExtractor, RelationshipVisitor} -import org.neo4j.kernel.impl.core.NodeManager - -import scala.collection.mutable - -object GeneratedQueryStructure extends CodeStructure[GeneratedQuery] { - override def generateQuery(packageName: String, className: String, columns: Seq[String], operatorIds: Map[String, Id], sourceSink: Option[SourceSink]) - (block: MethodStructure[_] => Unit)(implicit codeGenContext: CodeGenContext) = { - val generator: codegen.CodeGenerator = try { - codegen.CodeGenerator.generateCode(classOf[CodeStructure[_]].getClassLoader, sourceSink.map(sink => new SourceVisitor { - override protected def visitSource(reference: TypeReference, sourceCode: CharSequence): Unit = - sink.apply(reference.name(), sourceCode.toString) - }).getOrElse(BLANK_OPTION)) - } catch { - case e: Exception => throw new CantCompileQueryException(e.getMessage, e) - } - val execution = using(generator.generateClass(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)) - // the "COLUMNS" static field - clazz.staticField(typeRef[util.List[String]], "COLUMNS", Templates.asList( - columns.map(key => Expression.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) - val close = clazz.generate(Templates.CLOSE) - 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 => - using(method.tryBlock()) { body => - body.assign(typeRef[ResultRowImpl], "row", Templates.newResultRow) - block(Method(fields, body, new AuxGenerator(packageName, generator))) - body.expression(Expression.invoke(body.self(), fields.success)) - using(body.finallyBlock()) { then => - then.expression(Expression.invoke(body.self(), close)) - } - } - } - clazz.handle() - } - val query = using(generator.generateClass(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(Expression.invoke(Expression.newInstance(execution), MethodReference.constructorReference(execution, - typeRef[TaskCloser], - typeRef[QueryContext], - typeRef[EntityAccessor], - 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) - } - query - } - - def method[O <: AnyRef, R](name: String, params: TypeReference*)(implicit owner: Manifest[O], returns: Manifest[R]): MethodReference = - MethodReference.methodReference(typeReference(owner), typeReference(returns), name, 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: CypherType): TypeReference = cType match { - case symbols.CTNode => typeRef[Long] - case symbols.CTRelationship => typeRef[Long] - case symbols.CTString => typeRef[String] - case symbols.CTAny => typeRef[Object] - } - - def nullValue(cType: CypherType) = cType match { - case symbols.CTNode => Expression.constant(-1L) - case symbols.CTRelationship => Expression.constant(-1L) - case symbols.CTString => Expression.constant(null) - case symbols.CTAny => Expression.constant(null) - } -} - -private case class Fields(closer: FieldReference, - ro: FieldReference, - entityAccessor: FieldReference, - executionMode: FieldReference, - description: FieldReference, - tracer: FieldReference, - params: FieldReference, - closeable: FieldReference, - success: MethodReference) - -private class AuxGenerator(val packageName: String, val generator: codegen.CodeGenerator) { - - import org.neo4j.cypher.internal.spi.v3_0.GeneratedQueryStructure._ - - private val types: mutable.Map[Map[String, CypherType], TypeReference] = mutable.Map.empty - private var nameId = 0 - - def typeReference(structure: Map[String, CypherType]): TypeReference = { - types.getOrElseUpdate(structure, using(generator.generateClass(packageName, newName())) { clazz => - structure.foreach { - case (fieldName, fieldType) => clazz.field(lowerType(fieldType), fieldName) - } - clazz.handle() - }) - } - private def newName() = { - val name = "ValueType" + nameId - nameId += 1 - name - } -} - -private case class Method(fields: Fields, generator: CodeBlock, aux:AuxGenerator, tracing: Boolean = true, - event: Option[String] = None, var locals:Map[String,LocalVariable]=Map.empty)(implicit context: CodeGenContext) - extends MethodStructure[Expression] { - import org.neo4j.cypher.internal.spi.v3_0.GeneratedQueryStructure._ - - - 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 = TypeReference.parameterizedType(classOf[util.ArrayList[_]], valueType) - val tableType = TypeReference.parameterizedType(classOf[PrimitiveLongObjectMap[_]], valueType) - // the methods we use on those types - val get = MethodReference.methodReference(tableType, listType, "get", typeRef[Long]) - val put = MethodReference.methodReference(tableType, listType, "put", typeRef[Long], listType) - val add = MethodReference.methodReference(listType, typeRef[Boolean], "add", valueType) - - HashTable(valueType, listType, tableType, get, put, add) - - case LongsToListTable(structure, localMap) => - // compute the participating types - val valueType = aux.typeReference(structure) - val listType = TypeReference.parameterizedType(classOf[util.ArrayList[_]], valueType) - val tableType = TypeReference.parameterizedType(classOf[util.HashMap[_, _]], typeRef[CompositeKey], valueType) - // the methods we use on those types - val get = MethodReference.methodReference(tableType, listType, "get", typeRef[CompositeKey]) - val put = MethodReference.methodReference(tableType, listType, "put", typeRef[CompositeKey], listType) - val add = MethodReference.methodReference(listType, typeRef[Boolean], "add", valueType) - HashTable(valueType, listType, tableType, get, put, add) - } - } - - override def nextNode(targetVar: String, iterVar: String) = - generator.assign(typeRef[Long], targetVar, Expression.invoke(generator.load(iterVar), Methods.nextLong)) - - override def createRelExtractor(relVar: String) = - generator.assign(typeRef[RelationshipDataExtractor], relExtractor(relVar), Templates.newRelationshipDataExtractor) - - - override def nextRelationshipAndNode(toNodeVar: String, iterVar: String, direction: SemanticDirection, fromNodeVar: String, - relVar: String) = { - val extractor = relExtractor(relVar) - val startNode = Expression.invoke(generator.load(extractor), Methods.startNode) - val endNode = Expression.invoke(generator.load(extractor), Methods.endNode) - generator.expression(Expression.invoke(generator.load(iterVar), Methods.relationshipVisit, - Expression.invoke(generator.load(iterVar), Methods.nextLong), - generator.load(extractor))) - generator.assign(typeRef[Long], toNodeVar, DirectionConverter.toGraphDb(direction) match { - case Direction.INCOMING => startNode - case Direction.OUTGOING => endNode - case Direction.BOTH => Expression.ternary(Expression.eq(startNode, generator.load(fromNodeVar)), endNode, startNode) - }) - generator.assign(typeRef[Long], relVar, Expression.invoke(generator.load(extractor), Methods.relationship)) - } - - private def relExtractor(relVar: String) = s"${relVar}Extractor" - - override def nextRelationship(iterVar: String, ignored: SemanticDirection, relVar: String) = { - val extractor = relExtractor(relVar) - generator.expression(Expression.invoke(generator.load(iterVar), Methods.relationshipVisit, - Expression.invoke(generator.load(iterVar), Methods.nextLong), - generator.load(extractor))) - generator.assign(typeRef[Long], relVar, Expression.invoke(generator.load(extractor), Methods.relationship)) - } - - override def allNodesScan(iterVar: String) = - generator.assign(typeRef[PrimitiveLongIterator], iterVar, Expression.invoke(readOperations, Methods.nodesGetAll)) - - override def labelScan(iterVar: String, labelIdVar: String) = - generator.assign(typeRef[PrimitiveLongIterator], iterVar, - Expression.invoke(readOperations, Methods.nodesGetForLabel, generator.load(labelIdVar))) - - override def lookupLabelId(labelIdVar: String, labelName: String) = - generator.assign(typeRef[Int], labelIdVar, - Expression.invoke(readOperations, Methods.labelGetForName, Expression.constant(labelName))) - - override def lookupRelationshipTypeId(typeIdVar: String, typeName: String) = - generator.assign(typeRef[Int], typeIdVar, Expression - .invoke(readOperations, Methods.relationshipTypeGetForName, Expression.constant(typeName))) - - override def hasNext(iterVar: String) = - Expression.invoke(generator.load(iterVar), Methods.hasNext) - - override def whileLoop(test: Expression)(block: MethodStructure[Expression] => Unit) = - using(generator.whileLoop(test)) { body => - block(copy(generator = body)) - } - - override def forEach(varName: String, cypherType: CypherType, iterable: Expression)(block: MethodStructure[Expression] => Unit) = - using(generator.forEach(Parameter.param(lowerType(cypherType), 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 ternaryOperator(test: Expression, onTrue: Expression, onFalse: Expression): Expression = - Expression.ternary(test, onTrue, onFalse) - - override def returnSuccessfully() { - generator.expression(Expression.invoke(generator.self(), fields.success)) - generator.returns() - } - - override def declareCounter(name: String, initialValue: Expression): Unit = { - val variable = generator.declare(typeRef[Int], name) - locals = locals + (name -> variable) - generator.assign(variable, Expression.invoke(Methods.mathCastToInt, initialValue)) - } - - override def decreaseCounterAndCheckForZero(name: String): Expression = { - val local = locals(name) - generator.assign(local, Expression.sub(local, Expression.constant(1))) - Expression.eq(Expression.constant(0), local) - } - - override def counterEqualsZero(name: String): Expression = { - val local = locals(name) - Expression.eq(Expression.constant(0), local) - } - - override def setInRow(column: String, value: Expression) = - generator.expression(Expression.invoke(resultRow, Methods.set, Expression.constant(column), value)) - - override def visitorAccept() = using(generator.ifStatement(Expression.not( - Expression.invoke(generator.load("visitor"), Methods.visit, generator.load("row"))))) { body => - // NOTE: we are in this if-block if the visitor decided to terminate early (by returning false) - body.expression(Expression.invoke(body.self(), fields.success)) - body.returns() - } - - override def materializeNode(nodeIdVar: String) = Expression.invoke(nodeManager, Methods.newNodeProxyById, generator.load(nodeIdVar)) - - override def node(nodeIdVar: String) = Templates.newInstance(typeRef[NodeIdWrapper], generator.load(nodeIdVar)) - - - override def nullable(varName: String, cypherType: CypherType, onSuccess: Expression) = { - Expression.ternary( - Expression.eq(nullValue(cypherType), generator.load(varName)), - Expression.constant(null), - onSuccess) - } - - override def materializeRelationship(relIdVar: String) = Expression.invoke(nodeManager, Methods.newRelationshipProxyById, generator.load(relIdVar)) - - override def relationship(relIdVar: String) = Templates.newInstance(typeRef[RelationshipIdWrapper], generator.load(relIdVar)) - - override def trace[V](planStepId: String)(block: MethodStructure[Expression]=>V) = if(!tracing) block(this) - else { - val eventName = s"event_$planStepId" - using(generator.tryBlock(typeRef[QueryExecutionEvent], eventName, traceEvent(planStepId))) { body => - block(copy(event = Some(eventName), - generator = body)) - } - } - - private def traceEvent(planStepId: String) = Expression.invoke(tracer, Methods.executeOperator, - Expression.get(FieldReference.staticField(generator.owner(), typeRef[Id], planStepId))) - - override def incrementDbHits() = if(tracing) generator.expression(Expression.invoke(loadEvent, Methods.dbHit)) - - override def incrementRows() = if(tracing) generator.expression(Expression.invoke(loadEvent, Methods.row)) - - private def loadEvent = generator.load(event.getOrElse(throw new IllegalStateException("no current trace event"))) - - override def expectParameter(key: String, variableName: String) = { - using(generator.ifStatement(Expression.not(Expression.invoke(params, Methods.mapContains, Expression.constant(key))))) { block => - block.throwException(parameterNotFoundException(key)) - } - generator.assign(typeRef[Object], variableName, Expression.invoke(Methods.loadParameter, - Expression.invoke(params, Methods.mapGet, Expression.constant(key)))) - } - - override def constant(value: Object) = Expression.constant(value) - - override def not(value: Expression): Expression = Expression.not(value) - - override def threeValuedNot(value: Expression): Expression = Expression.invoke(Methods.not, value) - - override def threeValuedEquals(lhs: Expression, rhs: Expression) = Expression.invoke(Methods.ternaryEquals, lhs, rhs) - - override def eq(lhs: Expression, rhs: Expression) = Expression.eq(lhs, rhs) - - override def or(lhs: Expression, rhs: Expression) = Expression.or(lhs, rhs) - - override def threeValuedOr(lhs: Expression, rhs: Expression) = Expression.invoke(Methods.or, lhs, rhs) - - override def markAsNull(varName: String, cypherType: CypherType) = - generator.assign(lowerType(cypherType), varName, nullValue(cypherType)) - - override def notNull(varName: String, cypherType: CypherType) = - Expression.not(Expression.eq(nullValue(cypherType), generator.load(varName))) - - - override def nodeGetAllRelationships(iterVar: String, nodeVar: String, direction: SemanticDirection) = { - val local = generator.declare(typeRef[RelationshipIterator], iterVar) - Templates.handleExceptions(generator, fields.ro) { body => - body.assign(local, Expression.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) - Templates.handleExceptions(generator, fields.ro) { body => - val args = Seq(body.load(nodeVar), dir(direction)) ++ typeVars.map(body.load) - body.assign(local, Expression.invoke(readOperations, Methods.nodeGetRelationships, args: _*)) - } - } - - override def connectingRelationships(iterVar: String, fromNode: String, direction: SemanticDirection, toNode: String) = { - val local = generator.declare(typeRef[RelationshipIterator], iterVar) - Templates.handleExceptions(generator, fields.ro) { body => - body.assign(local, Expression.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) - Templates.handleExceptions(generator, fields.ro) { body => - val args = Seq(readOperations, body.load(fromNode), dir(direction), body.load(toNode)) ++ typeVars.map(body.load) - body.assign(local, Expression.invoke(Methods.connectingRelationships, args:_*)) - } - } - - override def load(varName: String) = generator.load(varName) - - override def add(lhs: Expression, rhs: Expression) = math(Methods.mathAdd, lhs, rhs) - - override def sub(lhs: Expression, rhs: Expression) = math(Methods.mathSub, lhs, rhs) - - override def mul(lhs: Expression, rhs: Expression) = math(Methods.mathMul, lhs, rhs) - - override def div(lhs: Expression, rhs: Expression) = math(Methods.mathDiv, lhs, rhs) - - override def mod(lhs: Expression, rhs: Expression) = math(Methods.mathMod, lhs, rhs) - - private def math(method: MethodReference, lhs: Expression, rhs: Expression): Expression = - // TODO: generate specialized versions for specific types - Expression.invoke(method, lhs, rhs) - - private def readOperations = Expression.get(generator.self(), fields.ro) - - private def nodeManager = Expression.get(generator.self(), fields.entityAccessor) - - private def resultRow = generator.load("row") - - private def tracer = Expression.get(generator.self(), fields.tracer) - - private def params = Expression.get(generator.self(), fields.params) - - private def parameterNotFoundException(key: String) = - Expression.invoke(Expression.newInstance(typeRef[ParameterNotFoundException]), - MethodReference.constructorReference(typeRef[ParameterNotFoundException], typeRef[String]), - Expression.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(values) - - override def toSet(value: Expression) = - Templates.newInstance(typeRef[util.HashSet[Object]], value) - - override def castToCollection(value: Expression) = Expression.invoke(Methods.toCollection, value) - - override def asMap(map: Map[String, Expression]) = { - Expression.invoke(Methods.arrayAsList, map.flatMap { - case (key, value) => Seq(Expression.constant(key), value) - }.toSeq: _*) - } - - override def method(resultType: JoinTableType, resultVar: String, methodName: String)(block: MethodStructure[Expression]=>Unit) = { - val returnType: TypeReference = joinTableType(resultType) - generator.assign(returnType, resultVar, Expression.invoke(generator.self(),MethodReference.methodReference(generator.owner(),returnType, methodName))) - using(generator.classGenerator().generateMethod(returnType, methodName)) { body => - block(copy(generator = body, event = None)) - 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,_) => TypeReference.parameterizedType(classOf[PrimitiveLongObjectMap[_]], - TypeReference.parameterizedType(classOf[util.ArrayList[_]], aux.typeReference(structure))) - case LongsToListTable(structure,_) => TypeReference.parameterizedType(classOf[util.HashMap[_,_]], typeRef[CompositeKey], - TypeReference.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 => Templates.newInstance(joinTableType(LongsToCountTable)) - case typ: LongsToListTable => Templates.newInstance(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, - Expression.invoke(generator.load(tableVar), Methods.countingTableGet, generator.load(keyVar))) - generator.expression(Expression.invoke(generator.load(tableVar), Methods.countingTablePut, generator.load(keyVar), - Expression.ternary( - Expression.eq(generator.load(countName), Expression - .get(staticField[LongKeyIntValueTable, Int]("NULL"))), - Expression.constant(1), - Expression.add(generator.load(countName), Expression.constant(1))))) - case LongsToCountTable => - val countName = context.namer.newVarName() - val keyName = context.namer.newVarName() - generator.assign(typeRef[CompositeKey], keyName, Expression.invoke(Methods.compositeKey, keyVars.map(generator.load): _*)) - generator.assign(typeRef[java.lang.Integer], countName, Expression.invoke(generator.load(tableVar), Methods.countingTableCompositeKeyGet, generator.load(keyName))) - generator.expression(Expression.invoke(generator.load(tableVar), Methods.countingTableCompositeKeyPut, - generator.load(keyName), Expression.ternary( - Expression.eq(generator.load(countName), Expression.constant(null)), - Expression.constant(1), - Expression.add(generator.load(countName), Expression.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, Expression.invoke(generator.load(tableVar), Methods.countingTableGet, generator.load(keyVar))) - using(generator.whileLoop(Expression.gt(times, Expression.constant(0)))) { body => - block(copy(generator=body)) - body.assign(times, Expression.sub(times, Expression.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, Expression.invoke(generator.load(tableVar), - Methods.countingTableCompositeKeyGet, - Expression.invoke(Methods.compositeKey, keyVars.map(generator.load): _*))) - generator.assign(times, - Expression.ternary( - Expression.eq(generator.load(intermediate.name()), Expression.constant(null)), - Expression.constant(-1), generator.load(intermediate.name()))) - - using(generator.whileLoop(Expression.gt(times, Expression.constant(0)))) { body => - block(copy(generator=body)) - body.assign(times, Expression.sub(times, Expression.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, Expression.invoke(generator.load(tableVar), hashTable.get, generator.load(keyVar))) - using(generator.ifStatement(Expression.not(Expression.eq(list, Expression.constant(null))))) { onTrue => - using(onTrue.forEach(Parameter.param(hashTable.valueType, elementName), list)) { forEach => - localVars.foreach { - case (local, field) => - val fieldType = lowerType(structure(field)) - forEach.assign(fieldType, local, Expression.get(forEach.load(elementName),FieldReference.field(hashTable.valueType, fieldType, field))) - } - 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, Expression.invoke(generator.load(tableVar),hashTable.get, Expression.invoke(Methods.compositeKey, keyVars.map(generator.load): _*))) - using(generator.ifStatement(Expression.not(Expression.eq(list, Expression.constant(null))))) { onTrue => - using(onTrue.forEach(Parameter.param(hashTable.valueType, elementName), list)) { forEach => - localVars.foreach { - case (local, field) => - val fieldType = lowerType(structure(field)) - forEach.assign(fieldType, local, Expression.get(forEach.load(elementName),FieldReference.field(hashTable.valueType, fieldType, field))) - } - block(copy(generator=forEach)) - } - } - } - - - - override def putField(structure: Map[String, CypherType], value: Expression, fieldType: CypherType, fieldName: String, localVar: String) = { - generator.put(value, field(structure, fieldType, fieldName), generator.load(localVar)) - } - - override def updateProbeTable(structure: Map[String, CypherType], 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; - generator.assign(list, Expression - .invoke(generator.load(tableVar), hashTable.get, generator.load(keyVar))) // list = tableVar.get(keyVar); - using(generator.ifStatement(Expression.eq(Expression.constant(null), generator.load(listName)))) - { onTrue => // if (null == list) - onTrue.assign(list, Templates.newInstance(hashTable.listType)) // list = new ListType(); - onTrue.expression(Expression.invoke(generator.load(tableVar), hashTable.put, generator.load(keyVar), - generator.load(listName))) // tableVar.put(keyVar, list); - } - generator.expression(Expression.invoke(list, hashTable.add, element)) // list.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, Expression.invoke(Methods.compositeKey, keyVars.map(generator.load): _*)) - generator.assign(list, Expression - .invoke(generator.load(tableVar), hashTable.get, generator.load(keyName))) // list = tableVar.get(keyVar); - using(generator.ifStatement(Expression.eq(Expression.constant(null), generator.load(listName)))) - { onTrue => // if (null == list) - onTrue.assign(list, Templates.newInstance(hashTable.listType)) // list = new ListType(); - onTrue.expression(Expression.invoke(generator.load(tableVar), hashTable.put, generator.load(keyName), - generator.load(listName))) // tableVar.put(keyVar, list); - } - generator.expression(Expression.invoke(list, hashTable.add, element)) // list.add( element ); - - - } - - override def declareProperty(propertyVar: String) = { - val localVariable = generator.declare(typeRef[Object], propertyVar) - locals = locals + (propertyVar -> localVariable) - generator.assign(localVariable, Expression.constant(null)) - } - - override def declare(varName: String, cypherType: CypherType) = { - val localVariable = generator.declare(lowerType(cypherType), varName) - locals = locals + (varName -> localVariable) - generator.assign(localVariable, nullValue(cypherType)) - } - - override def hasLabel(nodeVar: String, labelVar: String, predVar: String) = { - val local = locals(predVar) - Templates.handleExceptions(generator, fields.ro) { inner => - val invoke = Expression.invoke(readOperations, Methods.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 = Expression.invoke(generator.load(relExtractor(relVar)), Methods.typeOf) - Templates.handleExceptions(generator, fields.ro) { inner => - val invoke = Expression.invoke(readOperations, Methods.relationshipTypeGetName, typeOfRel) - inner.assign(variable, invoke) - 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 = locals + (name -> localVariable) - generator.assign(localVariable, Expression.constant(initialValue)) - } - - override def updateFlag(name: String, newValue: Boolean) = { - generator.assign(locals(name), Expression.constant(newValue)) - } - - override def declarePredicate(name: String) = { - locals = locals + (name -> generator.declare(typeRef[Boolean], name)) - } - - - override def nodeGetPropertyForVar(nodeIdVar: String, propIdVar: String, propValueVar: String) = { - val local = locals(propValueVar) - Templates.handleExceptions(generator, fields.ro) { body => - - body.assign(local, Expression.invoke(readOperations, Methods.nodeGetProperty, body.load(nodeIdVar), body.load(propIdVar))) - - } - } - - override def nodeGetPropertyById(nodeIdVar: String, propId: Int, propValueVar: String) = { - val local = locals(propValueVar) - Templates.handleExceptions(generator, fields.ro) { body => - body.assign(local, Expression.invoke(readOperations, Methods.nodeGetProperty, body.load(nodeIdVar), Expression.constant(propId))) - } - } - - override def relationshipGetPropertyForVar(relIdVar: String, propIdVar: String, propValueVar: String) = { - val local = locals(propValueVar) - Templates.handleExceptions(generator, fields.ro) { body => - body.assign(local, Expression.invoke(readOperations, Methods.relationshipGetProperty, body.load(relIdVar), body.load(propIdVar))) - } - } - - override def relationshipGetPropertyById(relIdVar: String, propId: Int, propValueVar: String) = { - val local = locals(propValueVar) - Templates.handleExceptions(generator, fields.ro) { body => - body.assign(local, Expression.invoke(readOperations, Methods.relationshipGetProperty, body.load(relIdVar), Expression.constant(propId))) - } - } - - override def lookupPropertyKey(propName: String, propIdVar: String) = - generator.assign(typeRef[Int], propIdVar, Expression.invoke(readOperations, Methods.propertyKeyGetForName ,Expression.constant(propName))) - - override def newIndexDescriptor(descriptorVar: String, labelVar: String, propKeyVar: String) = { - generator.assign(typeRef[IndexDescriptor], descriptorVar, - Templates.newInstance(typeRef[IndexDescriptor], generator.load(labelVar), generator.load(propKeyVar)) - ) - } - - override def indexSeek(iterVar: String, descriptorVar: String, value: Expression) = { - val local = generator.declare(typeRef[PrimitiveLongIterator], iterVar) - Templates.handleExceptions(generator, fields.ro) { body => - body.assign(local, Expression.invoke(readOperations, Methods.nodesGetFromIndexLookup, generator.load(descriptorVar), value )) - } - } - - override def indexUniqueSeek(nodeVar: String, descriptorVar: String, value: Expression) = { - val local = generator.declare(typeRef[Long], nodeVar) - Templates.handleExceptions(generator, fields.ro) { body => - body.assign(local, Expression.invoke(readOperations, Methods.nodeGetUniqueFromIndexLookup, generator.load(descriptorVar), value )) - } - } - - override def coerceToBoolean(propertyExpression: Expression): Expression = - Expression.invoke(Methods.coerceToPredicate, propertyExpression) - - override def newTableValue(targetVar: String, structure: Map[String, CypherType]) = { - val valueType = aux.typeReference(structure) - generator.assign(valueType, targetVar, Templates.newInstance(valueType)) - generator.load(targetVar) - } - - private def field(structure: Map[String, CypherType], fieldType: CypherType, fieldName: String) = { - FieldReference.field(aux.typeReference(structure), lowerType(fieldType), fieldName) - } -} - -private object Methods { - - import GeneratedQueryStructure.{method, typeRef} - - val countingTablePut = method[PrimitiveLongIntMap, Int]("put", typeRef[Long], typeRef[Int]) - val countingTableCompositeKeyPut = method[util.HashMap[_, _], Int]("put", typeRef[CompositeKey], typeRef[Int]) - val countingTableGet = method[PrimitiveLongIntMap, Int]("get", typeRef[Long]) - val countingTableCompositeKeyGet = method[util.HashMap[_, _], Int]("get", typeRef[CompositeKey]) - val compositeKey = method[CompiledConversionUtils, CompositeKey]("compositeKey", typeRef[Array[Long]]) - val hasNext = method[PrimitiveLongIterator, Boolean]("hasNext") - val arrayAsList = method[MapUtil, util.Map[String, Object]]("map", typeRef[Array[Object]]) - val relationshipVisit = method[RelationshipIterator, Boolean]("relationshipVisit", typeRef[Long], typeRef[RelationshipVisitor[RuntimeException]]) - val relationship = method[RelationshipDataExtractor, Long]("relationship", typeRef[Long]) - 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[Long], typeRef[Direction]) - val connectingRelationships = method[CompiledExpandUtils, RelationshipIterator]("connectingRelationships", typeRef[ReadOperations], typeRef[Long], typeRef[Long], typeRef[Direction], 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 mapGet = method[util.Map[String, Object], Object]("get", typeRef[String]) - val mapContains = method[util.Map[String, Object], Boolean]("containsKey", typeRef[String]) - 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 nodesGetAll = method[ReadOperations, PrimitiveLongIterator]("nodesGetAll") - val nodeGetProperty = method[ReadOperations, Object]("nodeGetProperty") - 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") - 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 newNodeProxyById = method[EntityAccessor, Node]("newNodeProxyById") - val nodeId = method[NodeIdWrapper, Long]("id") - val relId = method[RelationshipIdWrapper, Long]("id") - val newRelationshipProxyById = method[EntityAccessor, Relationship]("newRelationshipProxyById") - val set = method[ResultRowImpl, Unit]("set", typeRef[String], typeRef[Object]) - val visit = method[ResultVisitor[_], Boolean]("visit", typeRef[ResultRow]) - val executeOperator = method[QueryExecutionTracer, QueryExecutionEvent]("executeOperator", typeRef[Id]) - val dbHit = method[QueryExecutionEvent, Unit]("dbHit") - val row = method[QueryExecutionEvent, Unit]("row") -} - -private object Templates { - import GeneratedQueryStructure.{method, param, staticField, typeRef} - - def newInstance(valueType: TypeReference, args: Expression*): Expression = { - Expression.invoke(Expression.newInstance(valueType), MethodReference.constructorReference(valueType), args:_*) - } - - val newLongObjectMap = Expression.invoke(method[Primitive,PrimitiveLongObjectMap[_]]("longObjectMap")) - val newCountingMap = Expression.invoke(method[Primitive,PrimitiveLongIntMap]("longIntMap")) - - def asList(values: Seq[Expression]): Expression = Expression.invoke( - methodReference(typeRef[util.Arrays], typeRef[util.List[String]], "asList", typeRef[Array[String]]), - values: _*) - - def handleExceptions[V](generate: CodeBlock, ro: FieldReference)(block: CodeBlock => V) = using(generate.tryBlock()) { body => - // the body of the try - val result = block(body) - // the catch block - using(body.catchBlock(param[KernelException]("e"))) { handle => - 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") - )) - } - result - } - - 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")). - 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, ReadOperations]("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, NodeManager]("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(invoke(get(self(), typeRef[Provider[InternalPlanDescription]], "description"), - method[Provider[InternalPlanDescription], InternalPlanDescription]("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/internal/CypherStatementWithOptionsTest.scala b/community/cypher/cypher/src/test/java/org/neo4j/cypher/internal/CypherStatementWithOptionsTest.scala index 25450450fe332..2090330eb97a5 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 @@ -28,10 +28,6 @@ class CypherStatementWithOptionsTest extends CypherFunSuite { intercept[InvalidArgumentException](CypherStatementWithOptions("CYPHER planner=cost planner=rule RETURN 42")) } - test("should not allow inconsistent runtime options") { - intercept[InvalidArgumentException](CypherStatementWithOptions("CYPHER runtime=compiled runtime=interpreted RETURN 42")) - } - test("should not allow multiple versions") { intercept[InvalidArgumentException](CypherStatementWithOptions("CYPHER 2.3 CYPHER 3.0 RETURN 42")) } diff --git a/community/cypher/cypher/src/test/java/org/neo4j/cypher/internal/codegen/CompiledExpandUtilsTest.java b/community/cypher/cypher/src/test/java/org/neo4j/cypher/internal/codegen/CompiledExpandUtilsTest.java deleted file mode 100644 index 158b4bc304569..0000000000000 --- a/community/cypher/cypher/src/test/java/org/neo4j/cypher/internal/codegen/CompiledExpandUtilsTest.java +++ /dev/null @@ -1,96 +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.codegen; - -import org.junit.Test; - -import org.neo4j.graphdb.Direction; -import org.neo4j.kernel.api.ReadOperations; -import org.neo4j.kernel.api.exceptions.EntityNotFoundException; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import static org.neo4j.cypher.internal.codegen.CompiledExpandUtils.connectingRelationships; - -public class CompiledExpandUtilsTest -{ - @Test - public void shouldUseGivenOrderIfItHasLowerDegree() throws EntityNotFoundException - { - // GIVEN - ReadOperations readOperations = mock( ReadOperations.class ); - when( readOperations.nodeGetDegree( 1L, Direction.OUTGOING ) ).thenReturn( 1 ); - when( readOperations.nodeGetDegree( 2L, Direction.INCOMING ) ).thenReturn( 3 ); - - // WHEN - connectingRelationships( readOperations, 1L, Direction.OUTGOING, 2L ); - - // THEN - verify( readOperations, times( 1 ) ).nodeGetRelationships( 1L, Direction.OUTGOING ); - } - - @Test - public void shouldSwitchOrderIfItHasLowerDegree() throws EntityNotFoundException - { - // GIVEN - ReadOperations readOperations = mock( ReadOperations.class ); - when( readOperations.nodeGetDegree( 1L, Direction.OUTGOING ) ).thenReturn( 3 ); - when( readOperations.nodeGetDegree( 2L, Direction.INCOMING ) ).thenReturn( 1 ); - - // WHEN - connectingRelationships( readOperations, 1L, Direction.OUTGOING, 2L ); - - // THEN - verify( readOperations, times( 1 ) ).nodeGetRelationships( 2L, Direction.INCOMING ); - } - - @Test - public void shouldUseGivenOrderIfItHasLowerDegreeWithTypes() throws EntityNotFoundException - { - // GIVEN - ReadOperations readOperations = mock( ReadOperations.class ); - when( readOperations.nodeGetDegree( 1L, Direction.OUTGOING, 1 ) ).thenReturn( 1 ); - when( readOperations.nodeGetDegree( 2L, Direction.INCOMING, 1 ) ).thenReturn( 3 ); - - // WHEN - connectingRelationships( readOperations, 1L, Direction.OUTGOING, 2L, 1 ); - - // THEN - verify( readOperations, times( 1 ) ).nodeGetRelationships( 1L, Direction.OUTGOING, 1 ); - } - - @Test - public void shouldSwitchOrderIfItHasLowerDegreeWithTypes() throws EntityNotFoundException - { - // GIVEN - ReadOperations readOperations = mock( ReadOperations.class ); - when( readOperations.nodeGetDegree( 1L, Direction.OUTGOING, 1 ) ).thenReturn( 3 ); - when( readOperations.nodeGetDegree( 2L, Direction.INCOMING, 1 ) ).thenReturn( 1 ); - - // WHEN - connectingRelationships( readOperations, 1L, Direction.OUTGOING, 2L, 1 ); - - // THEN - verify( readOperations, times( 1 ) ).nodeGetRelationships( 2L, Direction.INCOMING, 1 ); - } - -} diff --git a/community/cypher/cypher/src/test/java/org/neo4j/cypher/internal/javacompat/ExecutionResultTest.java b/community/cypher/cypher/src/test/java/org/neo4j/cypher/internal/javacompat/ExecutionResultTest.java index aebbad2f2294a..3e425916b2930 100644 --- a/community/cypher/cypher/src/test/java/org/neo4j/cypher/internal/javacompat/ExecutionResultTest.java +++ b/community/cypher/cypher/src/test/java/org/neo4j/cypher/internal/javacompat/ExecutionResultTest.java @@ -108,102 +108,6 @@ public void shouldThrowAppropriateExceptionAlsoWhenVisiting() throws Exception db.execute( "RETURN rand()/0" ).accept( row -> true ); } - @Test - public void shouldBePossibleToConsumeCompiledExecutionResultsWithIterator() - { - // Given - createNode(); - createNode(); - - // When - List> listResult; - try ( Result result = db.execute( "CYPHER runtime=compiled MATCH (n) RETURN n" ) ) - { - listResult = Iterators.asList( result ); - } - - // Then - assertThat( listResult, hasSize( 2 ) ); - } - - @Test - public void shouldBePossibleToCloseNotFullyConsumedCompiledExecutionResults() - { - // Given - createNode(); - createNode(); - - // When - Map firstRow = null; - try ( Result result = db.execute( "CYPHER runtime=compiled MATCH (n) RETURN n" ) ) - { - if ( result.hasNext() ) - { - firstRow = result.next(); - } - } - - // Then - assertThat( firstRow, notNullValue() ); - } - - @Test - public void shouldBePossibleToConsumeCompiledExecutionResultsWithVisitor() - { - // Given - createNode(); - createNode(); - - // When - final List listResult = new ArrayList<>(); - try ( Result result = db.execute( "CYPHER runtime=compiled MATCH (n) RETURN n" ) ) - { - result.accept( row -> { - listResult.add( row ); - return true; - } ); - } - - // Then - assertThat( listResult, hasSize( 2 ) ); - } - - @Test - public void shouldBePossibleToCloseNotFullyVisitedCompiledExecutionResult() - { - // Given - createNode(); - createNode(); - - // When - final List listResult = new ArrayList<>(); - try ( Result result = db.execute( "CYPHER runtime=compiled MATCH (n) RETURN n" ) ) - { - result.accept( row -> { - listResult.add( row ); - // return false so that no more result rows would be visited - return false; - } ); - } - - // Then - assertThat( listResult, hasSize( 1 ) ); - } - - @Test - public void shouldBePossibleToCloseNotConsumedCompiledExecutionResult() - { - // Given - createNode(); - - // When - try ( Result ignore = db.execute( "CYPHER runtime=compiled MATCH (n) RETURN n" ) ) - { - // Then - // just close result without consuming it - } - } - private void createNode() { try ( Transaction tx = db.beginTx() ) 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 daaca5d762519..06e206f59fc19 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 @@ -29,7 +29,6 @@ import org.neo4j.cypher.internal.compiler.v3_0.tracing.rewriters.RewriterStepSeq import org.neo4j.cypher.internal.frontend.v3_0.InputPosition import org.neo4j.cypher.internal.frontend.v3_0.notification.CartesianProductNotification import org.neo4j.cypher.internal.frontend.v3_0.test_helpers.CypherFunSuite -import org.neo4j.cypher.internal.spi.v3_0.GeneratedQueryStructure import org.neo4j.logging.NullLog class CartesianProductNotificationAcceptanceTest extends CypherFunSuite with GraphDatabaseTestSupport { @@ -114,11 +113,10 @@ class CartesianProductNotificationAcceptanceTest extends CypherFunSuite with Gra nonIndexedLabelWarningThreshold = 10000L ), Clock.systemUTC(), - GeneratedQueryStructure, new WrappedMonitors3_0(kernelMonitors), new StringInfoLogger3_0(NullLog.getInstance), plannerName = Some(IDPPlannerName), - runtimeName = Some(CompiledRuntimeName), + runtimeName = Some(InterpretedRuntimeName), updateStrategy = None, rewriterSequencer = RewriterStepSequencer.newValidating, publicTypeConverter = identity 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 4409a08d5c7ea..d8a41bb14f0ab 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 @@ -79,14 +79,6 @@ class CypherCompatibilityTest extends ExecutionEngineFunSuite with RunWithConfig } } - //TODO fix this test - ignore("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") - } - } test("should handle profile in interpreted runtime") { runWithConfig() { @@ -144,39 +136,6 @@ class CypherCompatibilityTest extends ExecutionEngineFunSuite with RunWithConfig } } - test("should not fail if asked to execute query with runtime=compiled on simple query") { - runWithConfig(GraphDatabaseSettings.cypher_hints_error -> "true") { - db => - db.execute("MATCH (n:Movie) RETURN n") - db.execute("CYPHER runtime=compiled MATCH (n:Movie) RETURN n") - shouldHaveNoWarnings(db.execute("EXPLAIN CYPHER runtime=compiled MATCH (n:Movie) RETURN n")) - } - } - - test("should fail if asked to execute query with runtime=compiled instead of falling back to interpreted if hint errors turned on") { - runWithConfig(GraphDatabaseSettings.cypher_hints_error -> "true") { - db => - intercept[QueryExecutionException]( - db.execute(s"EXPLAIN CYPHER runtime=compiled $querySupportedByCostButNotCompiledRuntime") - ).getStatusCode should equal("Neo.ClientError.Statement.ArgumentError") - } - } - - test("should not fail if asked to execute query with runtime=compiled and instead fallback to interpreted and return a warning if hint errors turned off") { - runWithConfig(GraphDatabaseSettings.cypher_hints_error -> "false") { - db => - val result = db.execute(s"EXPLAIN CYPHER runtime=compiled $querySupportedByCostButNotCompiledRuntime") - shouldHaveWarning(result, Status.Statement.RuntimeUnsupportedWarning) - } - } - - test("should not fail if asked to execute query with runtime=compiled and instead fallback to interpreted and return a warning by default") { - runWithConfig() { - db => - val result = db.execute(s"EXPLAIN CYPHER runtime=compiled $querySupportedByCostButNotCompiledRuntime") - shouldHaveWarning(result, Status.Statement.RuntimeUnsupportedWarning) - } - } test("should not fail nor generate a warning if asked to execute query without specifying runtime, knowing that compiled is default but will fallback silently to interpreted") { runWithConfig() { diff --git a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/DumpToStringAcceptanceTest.scala b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/DumpToStringAcceptanceTest.scala index 7eb9dfc79b186..1d680c23447fa 100644 --- a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/DumpToStringAcceptanceTest.scala +++ b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/DumpToStringAcceptanceTest.scala @@ -24,7 +24,7 @@ class DumpToStringAcceptanceTest extends ExecutionEngineFunSuite with NewPlanner test("format node") { createNode(Map("prop1" -> "A", "prop2" -> 2)) - executeWithAllPlannersAndRuntimesAndCompatibilityMode("match (n) return n").dumpToString() should + executeWithAllPlannersAndCompatibilityMode("match (n) return n").dumpToString() should equal( """+----------------------------+ || n | |+----------------------------+ @@ -37,7 +37,7 @@ class DumpToStringAcceptanceTest extends ExecutionEngineFunSuite with NewPlanner test("format relationship") { relate(createNode(), createNode(), "T", Map("prop1" -> "A", "prop2" -> 2)) - executeWithAllPlannersAndRuntimesAndCompatibilityMode("match ()-[r]->() return r").dumpToString() should equal("""+--------------------------+ + executeWithAllPlannersAndCompatibilityMode("match ()-[r]->() return r").dumpToString() should equal("""+--------------------------+ || r | |+--------------------------+ || :T[0]{prop1:"A",prop2:2} | @@ -47,7 +47,7 @@ class DumpToStringAcceptanceTest extends ExecutionEngineFunSuite with NewPlanner } test("format collection of maps") { - executeWithAllPlannersAndRuntimesAndCompatibilityMode( """RETURN [{ inner: 'Map1' }, { inner: 'Map2' }]""").dumpToString() should + executeWithAllPlannersAndCompatibilityMode( """RETURN [{ inner: 'Map1' }, { inner: 'Map2' }]""").dumpToString() should equal( """+----------------------------------------+ || [{ inner: 'Map1' }, { inner: 'Map2' }] | |+----------------------------------------+ diff --git a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/EqualsTest.scala b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/EqualsTest.scala index dc9cd80f3805d..3ca284702d3c2 100644 --- a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/EqualsTest.scala +++ b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/EqualsTest.scala @@ -76,7 +76,7 @@ class EqualsTest extends ExecutionEngineFunSuite with NewPlannerTestSupport { // given createLabeledNode("Person") - intercept[IncomparableValuesException](executeWithAllPlannersAndRuntimesAndCompatibilityMode("MATCH (b) WHERE b = {param} RETURN b", + intercept[IncomparableValuesException](executeWithAllPlannersAndCompatibilityMode("MATCH (b) WHERE b = {param} RETURN b", "param" -> Map("name" -> "John Silver"))) } @@ -84,7 +84,7 @@ class EqualsTest extends ExecutionEngineFunSuite with NewPlannerTestSupport { // given createLabeledNode("Person") - intercept[IncomparableValuesException](executeWithAllPlannersAndRuntimesAndCompatibilityMode("MATCH (b) WHERE {param} = b RETURN b", "param" -> Map("name" -> "John Silver"))) + intercept[IncomparableValuesException](executeWithAllPlannersAndCompatibilityMode("MATCH (b) WHERE {param} = b RETURN b", "param" -> Map("name" -> "John Silver"))) } test("should allow equals between node and node") { @@ -121,21 +121,21 @@ class EqualsTest extends ExecutionEngineFunSuite with NewPlannerTestSupport { // given relate(createLabeledNode("Person"), createLabeledNode("Person")) - intercept[IncomparableValuesException](executeWithAllPlannersAndRuntimesAndCompatibilityMode("MATCH (a)-[b]->() RETURN a = b")) + intercept[IncomparableValuesException](executeWithAllPlannersAndCompatibilityMode("MATCH (a)-[b]->() RETURN a = b")) } test("should reject equals between relationship and node") { // given relate(createLabeledNode("Person"), createLabeledNode("Person")) - intercept[IncomparableValuesException](executeWithAllPlannersAndRuntimesAndCompatibilityMode("MATCH (a)-[b]->() RETURN b = a")) + intercept[IncomparableValuesException](executeWithAllPlannersAndCompatibilityMode("MATCH (a)-[b]->() RETURN b = a")) } test("should be able to send in node via parameter") { // given val node = createLabeledNode("Person") - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode("MATCH (b) WHERE b = {param} RETURN b", "param" -> node) + val result = executeWithAllPlannersAndCompatibilityMode("MATCH (b) WHERE b = {param} RETURN b", "param" -> node) result.toList should equal(List(Map("b" -> node))) } @@ -143,7 +143,7 @@ class EqualsTest extends ExecutionEngineFunSuite with NewPlannerTestSupport { // given val rel = relate(createLabeledNode("Person"), createLabeledNode("Person")) - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode("MATCH (:Person)-[r]->(:Person) WHERE r = {param} RETURN r", "param" -> rel) + val result = executeWithAllPlannersAndCompatibilityMode("MATCH (:Person)-[r]->(:Person) WHERE r = {param} RETURN r", "param" -> rel) result.toList should equal(List(Map("r" -> rel))) } @@ -152,7 +152,7 @@ class EqualsTest extends ExecutionEngineFunSuite with NewPlannerTestSupport { val node = createLabeledNode("Person") relate(node, node) - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode("MATCH (a:Person)-->(b:Person) WHERE a = b RETURN a") + val result = executeWithAllPlannersAndCompatibilityMode("MATCH (a:Person)-->(b:Person) WHERE a = b RETURN a") result.toList should equal(List(Map("a" -> node))) } diff --git a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/ExecutionEngineIT.scala b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/ExecutionEngineIT.scala index e38d0d64e79ba..91008e2dbe180 100644 --- a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/ExecutionEngineIT.scala +++ b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/ExecutionEngineIT.scala @@ -563,21 +563,6 @@ class ExecutionEngineIT extends CypherFunSuite with GraphIcing { txBridge(service).hasTransaction shouldBe false } - test("should be possible to close compiled result after it is consumed") { - // given - val db = new TestGraphDatabaseFactory().newImpermanentDatabase() - - // when - val result = db.execute("CYPHER runtime=compiled MATCH (n) RETURN n") - result.accept(new ResultVisitor[RuntimeException] { - def visit(row: ResultRow) = true - }) - - result.close() - - // then - // call to close actually worked - } test("should not refer to stale plan context in the cached execution plans") { // given diff --git a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/ExecutionEngineTest.scala b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/ExecutionEngineTest.scala index ec8b315e80fb8..4dd27113de658 100644 --- a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/ExecutionEngineTest.scala +++ b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/ExecutionEngineTest.scala @@ -22,7 +22,6 @@ package org.neo4j.cypher import java.io.{File, PrintWriter} import java.util.concurrent.TimeUnit -import jdk.nashorn.internal.runtime.ScriptRuntime import org.neo4j.cypher.internal.ExecutionEngine import org.neo4j.cypher.internal.compiler.v3_0.CompilationPhaseTracer.CompilationPhase import org.neo4j.cypher.internal.compiler.v3_0.test_helpers.CreateTempFileTestSupport @@ -33,13 +32,11 @@ import org.neo4j.graphdb._ import org.neo4j.graphdb.config.Setting import org.neo4j.graphdb.factory.GraphDatabaseSettings import org.neo4j.io.fs.FileUtils -import org.neo4j.kernel.api.security.AccessMode -import org.neo4j.kernel.api.KernelTransaction.Type -import org.neo4j.kernel.{NeoStoreDataSource} -import org.neo4j.test.TestGraphDatabaseFactory import org.neo4j.kernel.NeoStoreDataSource +import org.neo4j.kernel.api.KernelTransaction.Type +import org.neo4j.kernel.api.security.AccessMode import org.neo4j.kernel.impl.coreapi.TopLevelTransaction -import org.neo4j.test.{ImpermanentGraphDatabase, TestGraphDatabaseFactory} +import org.neo4j.test.TestGraphDatabaseFactory import scala.collection.JavaConverters._ import scala.collection.mutable @@ -429,8 +426,8 @@ order by a.COL1""") relate(refNode, a, "X") - executeWithAllPlannersAndRuntimesAndCompatibilityMode("match (a)-->(b) where a = {a} return b", "a" -> a) should have size 1 - executeWithAllPlannersAndRuntimesAndCompatibilityMode("match (a)-->(b) where a = {a} return b", "a" -> b) shouldBe empty + executeWithAllPlannersAndCompatibilityMode("match (a)-->(b) where a = {a} return b", "a" -> a) should have size 1 + executeWithAllPlannersAndCompatibilityMode("match (a)-->(b) where a = {a} return b", "a" -> b) shouldBe empty } test("should handle parameters names as variables") { @@ -635,7 +632,7 @@ order by a.COL1""") relate(a, b) relate(b, c) - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode("MATCH (n)-[r]->(m) WHERE n = {a} AND m = {b} RETURN *", "a"->a, "b"->c) + val result = executeWithAllPlannersAndCompatibilityMode("MATCH (n)-[r]->(m) WHERE n = {a} AND m = {b} RETURN *", "a"->a, "b"->c) result.toList shouldBe empty } @@ -934,7 +931,7 @@ order by a.COL1""") createNode("coll" -> Array(1, 2, 3), "bool" -> true) createLabeledNode("LABEL") - val foundNode = executeWithAllPlannersAndRuntimesAndCompatibilityMode("match (n:LABEL) where n.coll and n.bool return n").columnAs[Node]("n").next() + val foundNode = executeWithAllPlannersAndCompatibilityMode("match (n:LABEL) where n.coll and n.bool return n").columnAs[Node]("n").next() foundNode should equal(n) } diff --git a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/MutatingIntegrationTest.scala b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/MutatingIntegrationTest.scala index 5e0767d11de15..01bf8ca5f9127 100644 --- a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/MutatingIntegrationTest.scala +++ b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/MutatingIntegrationTest.scala @@ -317,7 +317,7 @@ class MutatingIntegrationTest extends ExecutionEngineFunSuite with Assertions wi } test("failed query should not leave dangling transactions") { - intercept[RuntimeException](executeWithAllPlannersAndRuntimesAndCompatibilityMode("RETURN 1 / 0")) + intercept[RuntimeException](executeWithAllPlannersAndCompatibilityMode("RETURN 1 / 0")) val contextBridge : ThreadToStatementContextBridge = graph.getDependencyResolver.resolveDependency(classOf[ThreadToStatementContextBridge]) contextBridge.getTopLevelTransactionBoundToThisThread( false ) should be(null) 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 d594f3201e0ec..4233b6a2ca47c 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 @@ -252,21 +252,6 @@ trait NewPlannerTestSupport extends CypherTestSupport { def executeWithCostPlannerOnly(queryText: String, params: (String, Any)*): InternalExecutionResult = monitoringNewPlanner(innerExecute(queryText, params: _*))(failedToUseNewPlanner(queryText))(unexpectedlyUsedNewRuntime(queryText)) - def executeWithAllPlannersAndRuntimesAndCompatibilityMode(queryText: String, params: (String, Any)*): InternalExecutionResult = { - val compatibilityResult = innerExecute(s"CYPHER 2.3 $queryText", params: _*) - val ruleResult = innerExecute(s"CYPHER planner=rule $queryText", params: _*) - val interpretedResult = innerExecute(s"CYPHER runtime=interpreted $queryText", params: _*) - val compiledResult = monitoringNewPlanner(innerExecute(s"CYPHER runtime=compiled $queryText", params: _*))(failedToUseNewPlanner(queryText))(failedToUseNewRuntime(queryText)) - - assertResultsAreSame(interpretedResult, compiledResult, queryText, "Diverging results between interpreted and compiled runtime") - assertResultsAreSame(compatibilityResult, interpretedResult, queryText, "Diverging results between compatibility and current") - assertResultsAreSame(ruleResult, interpretedResult, queryText, "Diverging results between rule planner and interpreted runtime") - compatibilityResult.close() - ruleResult.close() - interpretedResult.close() - compiledResult - } - private def assertResultsAreSame(result1: InternalExecutionResult, result2: InternalExecutionResult, queryText: String, errorMsg: String, replaceNaNs: Boolean = false) { withClue(errorMsg) { if (queryText.toLowerCase contains "order by") { diff --git a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/NodeIndexSeekAcceptanceTest.scala b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/NodeIndexSeekAcceptanceTest.scala index a61cb9b4986ad..3c0eba19c7586 100644 --- a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/NodeIndexSeekAcceptanceTest.scala +++ b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/NodeIndexSeekAcceptanceTest.scala @@ -30,7 +30,7 @@ class NodeIndexSeekAcceptanceTest extends ExecutionEngineFunSuite with NewPlanne setUpDatabaseForTests() // When - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode("MATCH (n:Crew) WHERE n.name = 'Neo' AND n.name = 'Morpheus' RETURN n") + val result = executeWithAllPlannersAndCompatibilityMode("MATCH (n:Crew) WHERE n.name = 'Neo' AND n.name = 'Morpheus' RETURN n") // Then result should (use("NodeIndexSeek") and be(empty)) @@ -73,7 +73,7 @@ class NodeIndexSeekAcceptanceTest extends ExecutionEngineFunSuite with NewPlanne graph.createIndex("L", "l") graph.createIndex("R", "r") - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode("MATCH (l:L {l: 9})-[:REL]->(r:R {r: 23}) RETURN l, r") + val result = executeWithAllPlannersAndCompatibilityMode("MATCH (l:L {l: 9})-[:REL]->(r:R {r: 23}) RETURN l, r") result should (use("NodeIndexSeek") and have size 100) } diff --git a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/NotificationAcceptanceTest.scala b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/NotificationAcceptanceTest.scala index 15a01bcef3ee4..6928602c07db7 100644 --- a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/NotificationAcceptanceTest.scala +++ b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/NotificationAcceptanceTest.scala @@ -25,17 +25,11 @@ import org.neo4j.cypher.internal.frontend.v3_0.notification._ class NotificationAcceptanceTest extends ExecutionEngineFunSuite with NewPlannerTestSupport { test("Warn for cartesian product") { - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode("explain match (a)-->(b), (c)-->(d) return *") + val result = executeWithAllPlannersAndCompatibilityMode("explain match (a)-->(b), (c)-->(d) return *") result.notifications.toList should equal(List(CartesianProductNotification(InputPosition(0, 1, 1), Set("c", "d")))) } - test("Warn for cartesian product with runtime=compiled") { - val result = innerExecute("explain cypher runtime=compiled match (a)-->(b), (c)-->(d) return count(*)") - - result.notifications.toList should equal(List(CartesianProductNotification(InputPosition(0, 1, 1), Set("c", "d")), - RuntimeUnsupportedNotification)) - } test("Warn for cartesian product with runtime=interpreted") { val result = executeWithAllPlannersAndCompatibilityMode("explain cypher runtime=interpreted match (a)-->(b), (c)-->(d) return *") @@ -44,7 +38,7 @@ class NotificationAcceptanceTest extends ExecutionEngineFunSuite with NewPlanner } test("Don't warn for cartesian product when not using explain") { - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode("match (a)-->(b), (c)-->(d) return *") + val result = executeWithAllPlannersAndCompatibilityMode("match (a)-->(b), (c)-->(d) return *") result.notifications shouldBe empty } @@ -108,11 +102,6 @@ class NotificationAcceptanceTest extends ExecutionEngineFunSuite with NewPlanner result.notifications shouldBe empty } - test("warn when requesting runtime=compiled on an unsupported query") { - val result = innerExecute("EXPLAIN CYPHER runtime=compiled MATCH (a)-->(b), (c)-->(d) RETURN count(*)") - result.notifications should contain(RuntimeUnsupportedNotification) - } - test("warn once when a single index hint cannot be fulfilled") { val result = innerExecute("EXPLAIN MATCH (n:Person) USING INDEX n:Person(name) WHERE n.name = 'John' RETURN n") result.notifications.toSet should contain(IndexHintUnfulfillableNotification("Person", "name")) @@ -157,8 +146,8 @@ class NotificationAcceptanceTest extends ExecutionEngineFunSuite with NewPlanner } test("Warnings should work on potentially cached queries") { - val resultWithoutExplain = executeWithAllPlannersAndRuntimesAndCompatibilityMode("match (a)-->(b), (c)-->(d) return *") - val resultWithExplain = executeWithAllPlannersAndRuntimesAndCompatibilityMode("explain match (a)-->(b), (c)-->(d) return *") + val resultWithoutExplain = executeWithAllPlannersAndCompatibilityMode("match (a)-->(b), (c)-->(d) return *") + val resultWithExplain = executeWithAllPlannersAndCompatibilityMode("explain match (a)-->(b), (c)-->(d) return *") resultWithoutExplain shouldBe empty resultWithExplain.notifications.toList should equal(List(CartesianProductNotification(InputPosition(0, 1, 1), Set("c", "d")))) 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 6776d09abea65..af5f37b14719a 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 @@ -23,7 +23,7 @@ import org.neo4j.cypher.internal.compiler.v3_0 import org.neo4j.cypher.internal.compiler.v3_0.executionplan.InternalExecutionResult import org.neo4j.cypher.internal.compiler.v3_0.planDescription.InternalPlanDescription.Arguments.{DbHits, EstimatedRows, Rows, Signature} import org.neo4j.cypher.internal.compiler.v3_0.planDescription.{Argument, InternalPlanDescription} -import org.neo4j.cypher.internal.compiler.v3_0.spi.{QualifiedProcedureName, GraphStatistics} +import org.neo4j.cypher.internal.compiler.v3_0.spi.{GraphStatistics, QualifiedProcedureName} import org.neo4j.cypher.internal.compiler.v3_0.test_helpers.CreateTempFileTestSupport import org.neo4j.cypher.internal.frontend.v3_0.helpers.StringHelper.RichString import org.neo4j.cypher.internal.frontend.v3_0.symbols._ @@ -39,7 +39,7 @@ class ProfilerAcceptanceTest extends ExecutionEngineFunSuite with CreateTempFile createNode() createNode() - val result = profileWithAllPlannersAndRuntimes("MATCH (n) RETURN n") + val result = profileWithAllPlanners("MATCH (n) RETURN n") assertRows(3)(result)("AllNodesScan", "ProduceResults") assertDbHits(0)(result)("ProduceResults") @@ -51,7 +51,7 @@ class ProfilerAcceptanceTest extends ExecutionEngineFunSuite with CreateTempFile createNode() createNode() - val result = profileWithAllPlannersAndRuntimes("MATCH (n) RETURN (n:Foo)") + val result = profileWithAllPlanners("MATCH (n) RETURN (n:Foo)") assertRows(3)(result)("AllNodesScan", "ProduceResults") assertDbHits(0)(result)("ProduceResults") @@ -122,7 +122,7 @@ class ProfilerAcceptanceTest extends ExecutionEngineFunSuite with CreateTempFile relate( createLabeledNode("A"), createLabeledNode("B")) //WHEN - val result = profileWithAllPlannersAndRuntimes("match (n:A)-->(x:B) return *") + val result = profileWithAllPlanners("match (n:A)-->(x:B) return *") //THEN assertRows(1)(result)("ProduceResults", "Filter", "Expand(All)", "NodeByLabelScan") @@ -215,7 +215,7 @@ class ProfilerAcceptanceTest extends ExecutionEngineFunSuite with CreateTempFile createNode() //GIVEN - val result = profileWithAllPlannersAndRuntimes("MATCH (n) RETURN n.foo") + val result = profileWithAllPlanners("MATCH (n) RETURN n.foo") //WHEN THEN assertRows(1)(result)("ProduceResults") @@ -233,7 +233,7 @@ class ProfilerAcceptanceTest extends ExecutionEngineFunSuite with CreateTempFile createNode() // WHEN - val result = profileWithAllPlannersAndRuntimes("MATCH (n) optional match (n)-->(x) return x") + val result = profileWithAllPlanners("MATCH (n) optional match (n)-->(x) return x") // THEN assertDbHits(0)(result)("ProduceResults") @@ -254,7 +254,7 @@ class ProfilerAcceptanceTest extends ExecutionEngineFunSuite with CreateTempFile createNode() createNode() createNode() - val result = profileWithAllPlannersAndRuntimes("""MATCH (n) RETURN n LIMIT 1""") + val result = profileWithAllPlanners("""MATCH (n) RETURN n LIMIT 1""") // WHEN result.toList @@ -323,7 +323,7 @@ class ProfilerAcceptanceTest extends ExecutionEngineFunSuite with CreateTempFile test("should support profiling optional match queries") { createLabeledNode(Map("x" -> 1), "Label") - val result = profileWithAllPlannersAndRuntimes("match (a:Label {x: 1}) optional match (a)-[:REL]->(b) return a.x as A, b.x as B").toList.head + val result = profileWithAllPlanners("match (a:Label {x: 1}) optional match (a)-[:REL]->(b) return a.x as A, b.x as B").toList.head result("A") should equal(1) result("B") should equal(null.asInstanceOf[Int]) } @@ -420,13 +420,13 @@ class ProfilerAcceptanceTest extends ExecutionEngineFunSuite with CreateTempFile } test("should show expand without types in a simple form") { - val a = profileWithAllPlannersAndRuntimes("match (n)-->() return *") + val a = profileWithAllPlanners("match (n)-->() return *") a.executionPlanDescription().toString should include("()<--(n)") } test("should show expand with types in a simple form") { - val result = profileWithAllPlannersAndRuntimes("match (n)-[r:T]->() return *") + val result = profileWithAllPlanners("match (n)-[r:T]->() return *") result.executionPlanDescription().toString should include("(n)-[r:T]->()") } @@ -436,7 +436,7 @@ class ProfilerAcceptanceTest extends ExecutionEngineFunSuite with CreateTempFile createLabeledNode("Label1") // when - val result = profileWithAllPlannersAndRuntimes("match (n:Label1) return n") + val result = profileWithAllPlanners("match (n:Label1) return n") // then assertDbHits(2)(result)("NodeByLabelScan") @@ -448,7 +448,7 @@ class ProfilerAcceptanceTest extends ExecutionEngineFunSuite with CreateTempFile relate(createNode(), createNode()) // when - val result = profileWithAllPlannersAndRuntimes("match (n)-->(x) return x") + val result = profileWithAllPlanners("match (n)-->(x) return x") // then assertDbHits(3)(result)("Expand(All)") @@ -457,10 +457,10 @@ class ProfilerAcceptanceTest extends ExecutionEngineFunSuite with CreateTempFile test("should report correct dbhits and rows for literal addition") { // when - val result = profileWithAllPlannersAndRuntimes("return 5 + 3") + val result = profileWithAllPlanners("return 5 + 3") // then - assertDbHits(0)(result)("EmptyRow", "Projection", "ProduceResults") + assertDbHits(0)(result)("Projection", "ProduceResults") assertRows(1)(result)("ProduceResults") } @@ -469,7 +469,7 @@ class ProfilerAcceptanceTest extends ExecutionEngineFunSuite with CreateTempFile createNode("name" -> "foo") // when - val result = profileWithAllPlannersAndRuntimes("match (n) return n.name + 3") + val result = profileWithAllPlanners("match (n) return n.name + 3") // then assertDbHits(1)(result)("Projection") @@ -481,7 +481,7 @@ class ProfilerAcceptanceTest extends ExecutionEngineFunSuite with CreateTempFile createNode("name" -> 10) // when - val result = profileWithAllPlannersAndRuntimes("match (n) return n.name - 3") + val result = profileWithAllPlanners("match (n) return n.name - 3") // then assertDbHits(1)(result)("Projection") @@ -503,7 +503,7 @@ class ProfilerAcceptanceTest extends ExecutionEngineFunSuite with CreateTempFile createNode() createNode() - val result = profileWithAllPlannersAndRuntimes("match (n), (m) return n, m") + val result = profileWithAllPlanners("match (n), (m) return n, m") assertRows(16)(result)("CartesianProduct") } @@ -519,7 +519,7 @@ class ProfilerAcceptanceTest extends ExecutionEngineFunSuite with CreateTempFile graph.createIndex("Glass", "name") // when - val result = profileWithAllPlannersAndRuntimes( + val result = profileWithAllPlanners( "match (n:Glass {name: 'Seymour'})-[:R1]->(o)-[:R2]->(p:Glass) USING INDEX n:Glass(name) return p.name") // then @@ -584,34 +584,6 @@ class ProfilerAcceptanceTest extends ExecutionEngineFunSuite with CreateTempFile assertDbHits(4)(result)("Filter") } - test("joins with identical scans") { - //given - val corp = createLabeledNode("Company") - val a1 = createLabeledNode("Artist") - val a2 = createLabeledNode("Artist") - val c = createLabeledNode("Concert") - val v = createLabeledNode("Venue") - relate(corp, a1, "SIGNED_WITH") - relate(corp, a2, "SIGNED_WITH") - relate(a1, c, "PERFORMED_AT") - relate(a2, c, "PERFORMED_AT") - relate(c, v, "IN") - - //force a plan to have a scan on corp in both the lhs and the rhs of join - val query = - """MATCH (corp:Company)<-[:SIGNED_WITH]-(a1:Artist)-[:PERFORMED_AT]->(c:Concert)-[:IN]->(v:Venue) - |MATCH (corp)<-[:SIGNED_WITH]-(a2:Artist)-[:PERFORMED_AT]->(c) - |USING JOIN ON c,corp - |RETURN a1, a2, v""".stripMargin - - //when - val result = profileWithAllPlannersAndRuntimes(query) - - //then - assertDbHits(2)(result)("NodeByLabelScan") - assertRows(1)(result)("NodeByLabelScan") - } - test("distinct should not look up properties every time") { // GIVEN createNode("prop"-> 42) @@ -660,8 +632,6 @@ class ProfilerAcceptanceTest extends ExecutionEngineFunSuite with CreateTempFile def profileWithAllPlanners(q: String, params: (String, Any)*): InternalExecutionResult = profileWithPlanner(executeWithAllPlannersAndCompatibilityMode(_,_:_*), q, params:_*) - def profileWithAllPlannersAndRuntimes(q: String, params: (String, Any)*): InternalExecutionResult = profileWithPlanner(executeWithAllPlannersAndRuntimesAndCompatibilityMode(_,_:_*), q, params:_*) - override def profile(q: String, params: (String, Any)*): InternalExecutionResult = fail("Don't use profile all together in ProfilerAcceptanceTest") def legacyProfile(q: String, params: (String, Any)*): InternalExecutionResult = profileWithPlanner(innerExecute(_,_:_*), q, params:_*) 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 b6a1e71cb42eb..0ef6eabbc65f4 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 @@ -24,7 +24,7 @@ import java.util import org.neo4j.cypher.internal.QueryStatistics import org.neo4j.cypher.internal.compatibility.ExecutionResultWrapperFor3_0 import org.neo4j.cypher.internal.compiler.v3_0.executionplan.InternalExecutionResult -import org.neo4j.cypher.internal.compiler.v3_0.{CompiledRuntimeName, CostBasedPlannerName} +import org.neo4j.cypher.internal.compiler.v3_0.{InterpretedRuntimeName, CostBasedPlannerName} import org.neo4j.kernel.impl.query.{QueryExecutionMonitor, QuerySession} import org.scalatest.Assertions @@ -48,7 +48,7 @@ trait QueryStatisticsTestSupport { implicit val session = new QuerySession(null) { override def toString: String = s"test-session\ttest" } - val r = new ExecutionResultWrapperFor3_0(actual, CostBasedPlannerName.default, CompiledRuntimeName) + val r = new ExecutionResultWrapperFor3_0(actual, CostBasedPlannerName.default, InterpretedRuntimeName) 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 67816744fb3f7..e1939b04b6ab5 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 @@ -97,23 +97,6 @@ class RootPlanAcceptanceTest extends ExecutionEngineFunSuite { .shouldHaveRuntime(InterpretedRuntimeName) } - test("query that lacks support from the compiled runtime") { - given("CREATE ()") - .withCypherVersion(CypherVersion.v3_0) - .withRuntime(CompiledRuntimeName) - .shouldHaveCypherVersion(CypherVersion.v3_0) - .shouldHaveRuntime(InterpretedRuntimeName) - } - - test("query that should go through the compiled runtime") { - given("MATCH (a)-->(b) RETURN a") - .withCypherVersion(CypherVersion.v3_0) - .withRuntime(CompiledRuntimeName) - .shouldHaveCypherVersion(CypherVersion.v3_0) - .shouldHaveRuntime(CompiledRuntimeName) - .shouldHavePlanner(CostBasedPlannerName.default) - } - test("AllNodesScan should be the only child of the plan") { val description = given("match (n) return n").planDescription var children = description.getChildren @@ -126,22 +109,6 @@ class RootPlanAcceptanceTest extends ExecutionEngineFunSuite { children.get(0).getName should be("AllNodesScan") } - test("DbHits should contain proper values in compiled runtime") { - val description = given("match (n) return n") - .withRuntime(CompiledRuntimeName) - .planDescription - val children = description.getChildren - children should have size 1 - description.getArguments.get("DbHits") should equal(0) // ProduceResults has no hits - children.get(0).getArguments.get("DbHits") should equal(1) // AllNodesScan has 1 hit - } - - test("Rows should be properly formatted in compiled runtime") { - given("match (n) return n") - .withRuntime(CompiledRuntimeName) - .planDescription.getArguments.get("Rows") should equal(0) - } - test("DbHits should contain proper values in interpreted runtime") { val description = given("match (n) return n") .withRuntime(InterpretedRuntimeName) @@ -163,8 +130,7 @@ class RootPlanAcceptanceTest extends ExecutionEngineFunSuite { } for(planner <- Seq(IDPPlannerName, DPPlannerName, RulePlannerName); - runtime <- Seq(CompiledRuntimeName, InterpretedRuntimeName) - if !(planner == RulePlannerName && runtime == CompiledRuntimeName)) { + runtime <- Seq(InterpretedRuntimeName)) { test(s"Should report correct planner and runtime used $planner + $runtime") { given("match (n) return n") diff --git a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/SemanticCreateAcceptanceTest.scala b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/SemanticCreateAcceptanceTest.scala index 2c157c74de486..f2ea5a611498d 100644 --- a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/SemanticCreateAcceptanceTest.scala +++ b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/SemanticCreateAcceptanceTest.scala @@ -46,7 +46,7 @@ class SemanticCreateAcceptanceTest extends ExecutionEngineFunSuite with PatternG updateWithBothPlannersAndCompatibilityMode(s"CREATE $patternString") //find created pattern (cannot return * since everything might be unnamed) - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode(s"MATCH $patternString RETURN 42") + val result = executeWithAllPlannersAndCompatibilityMode(s"MATCH $patternString RETURN 42") result.toList should have size 1 //clean up diff --git a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/SemanticMergeAcceptanceTest.scala b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/SemanticMergeAcceptanceTest.scala index 9a26f9d77855b..21a172fb2d3af 100644 --- a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/SemanticMergeAcceptanceTest.scala +++ b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/SemanticMergeAcceptanceTest.scala @@ -45,7 +45,7 @@ class SemanticMergeAcceptanceTest updateWithBothPlannersAndCompatibilityMode(s"MERGE $patternString") //find created pattern (cannot return * since everything might be unnamed) - val result = executeWithAllPlannersAndRuntimesAndCompatibilityMode(s"MATCH $patternString RETURN 42") + val result = executeWithAllPlannersAndCompatibilityMode(s"MATCH $patternString RETURN 42") result.toList should have size 1 //clean up diff --git a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/StartPointFindingAcceptanceTest.scala b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/StartPointFindingAcceptanceTest.scala index b8b81dfa76759..359ee130922bc 100644 --- a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/StartPointFindingAcceptanceTest.scala +++ b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/StartPointFindingAcceptanceTest.scala @@ -26,7 +26,7 @@ class StartPointFindingAcceptanceTest extends ExecutionEngineFunSuite with NewPl test("Scan all nodes") { val nodes = Set(createNode("a"), createNode("b"), createNode("c")) - executeWithAllPlannersAndRuntimesAndCompatibilityMode("match (n) return n").columnAs[Node]("n").toSet should equal(nodes) + executeWithAllPlannersAndCompatibilityMode("match (n) return n").columnAs[Node]("n").toSet should equal(nodes) } test("Scan labeled node") { @@ -34,7 +34,7 @@ class StartPointFindingAcceptanceTest extends ExecutionEngineFunSuite with NewPl createLabeledNode("Person") val animals = Set(createLabeledNode("Animal"), createLabeledNode("Animal")) - executeWithAllPlannersAndRuntimesAndCompatibilityMode("match (n:Animal) return n").columnAs[Node]("n").toSet should equal(animals) + executeWithAllPlannersAndCompatibilityMode("match (n:Animal) return n").columnAs[Node]("n").toSet should equal(animals) } test("Seek node by id given on the left") { diff --git a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/codegen/CompiledConversionUtilsTest.scala b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/codegen/CompiledConversionUtilsTest.scala deleted file mode 100644 index 24ce73d5966e7..0000000000000 --- a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/codegen/CompiledConversionUtilsTest.scala +++ /dev/null @@ -1,143 +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.codegen - -import org.mockito.Mockito.when -import org.neo4j.cypher.internal.frontend.v3_0.CypherTypeException -import org.neo4j.cypher.internal.frontend.v3_0.test_helpers.CypherFunSuite -import org.neo4j.graphdb.{Node, Relationship} - -class CompiledConversionUtilsTest extends CypherFunSuite { - - val testPredicates = Seq( - (true, true), - (false, false), - (null, false), - (Array(), false), - (Array(1), true), - (Array("foo"), true), - (Array[Int](), false) - ) - - testPredicates.foreach { - case (v, expected) => - test(s"$v") { - CompiledConversionUtils.coerceToPredicate(v) should equal(expected) - } - } - - test("should throw for string and int") { - intercept[CypherTypeException](CompiledConversionUtils.coerceToPredicate("APA")) - intercept[CypherTypeException](CompiledConversionUtils.coerceToPredicate(12)) - } - - test("should convert List") { - import scala.collection.JavaConverters._ - - val col = CompiledConversionUtils.toCollection(List("a", "b", "c").asJava) - - col shouldBe a [java.util.Collection[_]] - col.asScala.toSeq should equal(Seq("a", "b", "c")) - } - - test("should throw if converting from non-collection") { - intercept[CypherTypeException](CompiledConversionUtils.toCollection("this is not a collection")) - } - - test("should handle null") { - CompiledConversionUtils.toCollection(null) shouldBe empty - } - - test("should be able to use a composite key in a hash map") { - //given - val theKey = CompiledConversionUtils.compositeKey(1l, 2L, 11L) - val theObject = mock[Object] - val theMap = Map(theKey -> theObject) - - //when/then - theMap(theKey) should equal(theObject) - } - - val testEquality = Seq( - (null, "foo") -> null, - (false, false) -> true, - (9007199254740993L, 9007199254740992D) -> false, - (9007199254740992D, 9007199254740993L) -> false, - (1, null) -> null, - ("foo", "foo") -> true, - ("foo", "bar") -> false, - (42L, 42) -> true, - (42, 43) -> false) - - testEquality.foreach { - case (v, expected) => - test(s"${v._1} == ${v._2}") { - CompiledConversionUtils.equals _ tupled v should equal(expected) - } - } - - val testOr = Seq( - (null, true) -> true, - (null, false) -> null, - (true, null) -> true, - (false, null) -> null, - (true, true) -> true, - (true, false) -> true, - (false, true) -> true, - (false, false) -> false) - - testOr.foreach { - case (v, expected) => - test(s"${v._1} || ${v._2}") { - CompiledConversionUtils.or _ tupled v should equal(expected) - } - } - - val testNot= Seq( - (null, null), - (false, true), - (true, false) - ) - - testNot.foreach { - case (v, expected) => - test(s"$v != $expected)") { - CompiledConversionUtils.not(v) should equal(expected) - } - } - - val node = mock[Node] - when(node.getId).thenReturn(11L) - val rel = mock[Relationship] - when(rel.getId).thenReturn(13L) - - val testLoadParameter = Seq( - (null, null), - (node, new NodeIdWrapper(11L)), - (rel, new RelationshipIdWrapper(13L)) - ) - - testLoadParameter.foreach { - case (v, expected) => - test(s"loadParameter($v) == $expected)") { - CompiledConversionUtils.loadParameter(v) should equal(expected) - } - } -} diff --git a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/codegen/CompiledMathHelperTest.scala b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/codegen/CompiledMathHelperTest.scala deleted file mode 100644 index 4e1da727b9b23..0000000000000 --- a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/codegen/CompiledMathHelperTest.scala +++ /dev/null @@ -1,123 +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.codegen - -import org.neo4j.cypher.internal.frontend.v3_0.CypherTypeException -import org.scalatest.prop.TableDrivenPropertyChecks -import org.scalatest.{Assertions, Matchers, PropSpec} - -class CompiledMathHelperTest extends PropSpec with TableDrivenPropertyChecks with Matchers with Assertions { - - val values: Seq[AnyRef] = - // The exclamation mark casts the expression to a AnyRef instead of a primitive - // To be as exhaustive as possible, the strategy is to do a cartesian product of all test values, - // and ensure that either we have defined behaviour, or that a runtime type exception is thrown - Seq( - 1 !, - 6789 !, - 3.14 !, - null, - "a", - true !, - false ! - ) - - property("+") { - forAll(getTable(CompiledMathHelper.add)) { - case (null, _, Right(result)) => result should equal(null) - case (_, null, Right(result)) => result should equal(null) - - case (l: java.lang.Double, r: Number, Right(result)) => result should equal(l + r.doubleValue()) - case (l: Number, r: java.lang.Double, Right(result)) => result should equal(l.doubleValue() + r) - case (l: java.lang.Float, r: Number, Right(result)) => result should equal(l + r.doubleValue()) - case (l: Number, r: java.lang.Float, Right(result)) => result should equal(l.doubleValue() + r) - case (l: Number, r: Number, Right(result)) => result should equal(l.longValue() + r.longValue()) - - case (l: Number, r: String, Right(result)) => result should equal(l.toString + r) - case (l: String, r: Number, Right(result)) => result should equal(l.toString + r) - case (l: String, r: String, Right(result)) => result should equal(l + r) - case (l: String, r: java.lang.Boolean, Right(result)) => result should equal(l + r) - case (l: java.lang.Boolean, r: String, Right(result)) => result should equal(l + r) - - case (_: Number, _: java.lang.Boolean, Left(exception)) => exception shouldBe a [CypherTypeException] - case (_: java.lang.Boolean, _: java.lang.Boolean, Left(exception)) => exception shouldBe a [CypherTypeException] - case (_: java.lang.Boolean, _: Number, Left(exception)) => exception shouldBe a [CypherTypeException] - - case (v1, v2, v3) => fail(s"Unspecified behaviour: $v1 + $v2 => $v3") - } - } - - property("-") { - forAll(getTable(CompiledMathHelper.subtract)) { - case (null, _, Right( result )) => result should equal( null ) - case (_, null, Right( result )) => result should equal( null ) - - case (l: java.lang.Double, r: Number, Right(result)) => result should equal(l - r.doubleValue()) - case (l: Number, r: java.lang.Double, Right(result)) => result should equal(l.doubleValue() - r) - case (l: java.lang.Float, r: Number, Right(result)) => result should equal(l - r.doubleValue()) - case (l: Number, r: java.lang.Float, Right(result)) => result should equal(l.doubleValue() - r) - case (l: Number, r: Number, Right(result)) => result should equal(l.longValue() - r.longValue()) - - case (l: Number, r: String, Left(exception)) => exception shouldBe a [CypherTypeException] - case (l: String, r: Number, Left(exception)) => exception shouldBe a [CypherTypeException] - case (l: String, r: String, Left(exception)) => exception shouldBe a [CypherTypeException] - case (l: String, r: java.lang.Boolean, Left(exception)) => exception shouldBe a [CypherTypeException] - case (l: java.lang.Boolean, r: String, Left(exception)) => exception shouldBe a [CypherTypeException] - - case (_: Number, _: java.lang.Boolean, Left(exception)) => exception shouldBe a [CypherTypeException] - case (_: java.lang.Boolean, _: java.lang.Boolean, Left(exception)) => exception shouldBe a [CypherTypeException] - case (_: java.lang.Boolean, _: Number, Left(exception)) => exception shouldBe a [CypherTypeException] - - case (v1, v2, v3) => fail(s"Unspecified behaviour: $v1 + $v2 => $v3") - } - } - - implicit class I(i: Int) { def ! = i: java.lang.Integer } - implicit class D(i: Double) { def ! = i: java.lang.Double } - implicit class Z(i: Boolean) { def ! = i: java.lang.Boolean } - - private def getTable(f: (AnyRef, AnyRef) => AnyRef) = { - - val cartesianProduct = (for (x <- values; y <- values) yield { - (x, y) - }).distinct - - val valuesWithResults = cartesianProduct.map { - case (l, r) => (l, r, throwableToLeft(f(l, r))) - } - - Table(("lhs", "rhs", "result"), valuesWithResults: _*) - } - - def throwableToLeft[T](block: => T): Either[java.lang.Throwable, T] = - try { - Right(block) - } catch { - case ex: Throwable => Left(ex) - } - - val inputs = Table[Any]("Number", 42, 42.1, 42L, 42.3F) - property("transformToInt") { - forAll(inputs) { - case x => CompiledMathHelper.transformToInt(x) should equal(42) - } - } - -} 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 d0a751038b741..cc5fa66d58e89 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 @@ -24,7 +24,6 @@ import org.neo4j.cypher.internal.CypherCompiler.{CLOCK, DEFAULT_QUERY_PLAN_TTL, import org.neo4j.cypher.internal.compatibility.WrappedMonitors3_0 import org.neo4j.cypher.internal.compiler.v3_0.tracing.rewriters.RewriterStepSequencer import org.neo4j.cypher.internal.compiler.v3_0.{CypherCompilerFactory, InfoLogger, _} -import org.neo4j.cypher.internal.spi.v3_0.GeneratedQueryStructure class CypherCompilerPerformanceTest extends GraphDatabaseFunSuite { @@ -183,12 +182,11 @@ class CypherCompilerPerformanceTest extends GraphDatabaseFunSuite { nonIndexedLabelWarningThreshold = 10000L ), clock = CLOCK, - structure = GeneratedQueryStructure, monitors = new WrappedMonitors3_0(kernelMonitors), logger = DEV_NULL, rewriterSequencer = RewriterStepSequencer.newPlain, plannerName = Some(IDPPlannerName), - runtimeName = Some(CompiledRuntimeName), + runtimeName = Some(InterpretedRuntimeName), updateStrategy = None, publicTypeConverter = identity ) diff --git a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/CypherPreParserTest.scala b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/CypherPreParserTest.scala index 1387361a5c0f3..2fbf4b79eaab0 100644 --- a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/CypherPreParserTest.scala +++ b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/CypherPreParserTest.scala @@ -39,23 +39,13 @@ class CypherPreParserTest extends CypherFunSuite with TableDrivenPropertyChecks ("CYPHER 2.2 planner = idp RETURN", PreParsedStatement("RETURN", Seq(ConfigurationOptions(Some(VersionOption("2.2")), Seq(IDPPlannerOption))), (1, 26, 25))), ("CYPHER planner =dp RETURN", PreParsedStatement("RETURN", Seq(ConfigurationOptions(None, Seq( DPPlannerOption))), (1, 20, 19))), - ("CYPHER runtime=interpreted RETURN", PreParsedStatement("RETURN", Seq(ConfigurationOptions(None, Seq(InterpretedRuntimeOption))), (1, 28, 27))), - ("CYPHER runtime=compiled RETURN", PreParsedStatement("RETURN", Seq(ConfigurationOptions(None, Seq(CompiledRuntimeOption))), (1, 25, 24))), - ("CYPHER 2.3 planner=cost runtime=interpreted RETURN", PreParsedStatement("RETURN", Seq( ConfigurationOptions(Some(VersionOption("2.3")), Seq(CostPlannerOption, InterpretedRuntimeOption))), (1, 45, 44))), - ("CYPHER 2.3 planner=cost runtime=compiled RETURN", PreParsedStatement("RETURN", Seq(ConfigurationOptions( - Some(VersionOption("2.3")), Seq(CostPlannerOption, CompiledRuntimeOption))), (1, 42, 41))), ("CYPHER 2.3 planner=dp runtime=interpreted RETURN", PreParsedStatement("RETURN", Seq(ConfigurationOptions( Some(VersionOption("2.3")), Seq(DPPlannerOption, InterpretedRuntimeOption))), (1, 43, 42))), - ("CYPHER 2.3 planner=dp runtime=compiled RETURN", PreParsedStatement("RETURN", Seq(ConfigurationOptions( - Some(VersionOption("2.3")), Seq(DPPlannerOption, CompiledRuntimeOption))), (1, 40, 39))), ("CYPHER 2.3 planner=idp runtime=interpreted RETURN", PreParsedStatement("RETURN", Seq(ConfigurationOptions (Some(VersionOption("2.3")), Seq(IDPPlannerOption, InterpretedRuntimeOption))), (1, 44, 43))), - ("CYPHER 2.3 planner=idp runtime=compiled RETURN", PreParsedStatement("RETURN", Seq(ConfigurationOptions( - Some(VersionOption("2.3")), Seq(IDPPlannerOption, CompiledRuntimeOption))), (1, 41, 40))), ("CYPHER 2.3 planner=idp runtime=interpreted RETURN", PreParsedStatement("RETURN", Seq(ConfigurationOptions - (Some(VersionOption("2.3")), Seq(IDPPlannerOption, InterpretedRuntimeOption))), (1, 44, 43))), ("explainmatch", PreParsedStatement("explainmatch", Seq.empty, (1, 1, 0))), ("CYPHER updateStrategy=eager RETURN", PreParsedStatement("RETURN", Seq(ConfigurationOptions(None, Seq(EagerOption))), (1, 29, 28))) ) diff --git a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/v3_0/CompilerComparisonTest.scala b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/v3_0/CompilerComparisonTest.scala index b7faa5e96ea95..5253a2c02942d 100644 --- a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/v3_0/CompilerComparisonTest.scala +++ b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/v3_0/CompilerComparisonTest.scala @@ -34,7 +34,7 @@ import org.neo4j.cypher.internal.compiler.v3_0.tracing.rewriters.RewriterStepSeq import org.neo4j.cypher.internal.frontend.v3_0.ast.Statement import org.neo4j.cypher.internal.frontend.v3_0.parser.CypherParser import org.neo4j.cypher.internal.spi.TransactionalContextWrapper -import org.neo4j.cypher.internal.spi.v3_0.{GeneratedQueryStructure, TransactionBoundPlanContext, TransactionBoundQueryContext} +import org.neo4j.cypher.internal.spi.v3_0.{TransactionBoundPlanContext, TransactionBoundQueryContext} import org.neo4j.cypher.javacompat.internal.GraphDatabaseCypherService import org.neo4j.cypher.{ExecutionEngineFunSuite, NewPlannerTestSupport, QueryStatisticsTestSupport} import org.neo4j.graphdb.factory.GraphDatabaseFactory @@ -304,7 +304,7 @@ class CompilerComparisonTest extends ExecutionEngineFunSuite with QueryStatistic plannerName = Some(plannerName), rewriterSequencer = rewriterSequencer, queryPlanner = queryPlanner, - runtimeBuilder = SilentFallbackRuntimeBuilder(InterpretedPlanBuilder(clock, monitors, identity), CompiledPlanBuilder(clock,GeneratedQueryStructure)), + runtimeBuilder = InterpretedRuntimeBuilder(InterpretedPlanBuilder(clock, monitors, identity)), semanticChecker = checker, config = config, updateStrategy = None, diff --git a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/v3_0/CypherCompilerAstCacheAcceptanceTest.scala b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/v3_0/CypherCompilerAstCacheAcceptanceTest.scala index c772d93d2df59..f01fed9bff06c 100644 --- a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/v3_0/CypherCompilerAstCacheAcceptanceTest.scala +++ b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/v3_0/CypherCompilerAstCacheAcceptanceTest.scala @@ -27,7 +27,6 @@ import org.neo4j.cypher.internal.compiler.v3_0.executionplan.ExecutionPlan import org.neo4j.cypher.internal.compiler.v3_0.tracing.rewriters.RewriterStepSequencer import org.neo4j.cypher.internal.frontend.v3_0.ast.Statement import org.neo4j.cypher.internal.frontend.v3_0.test_helpers.CypherFunSuite -import org.neo4j.cypher.internal.spi.v3_0.GeneratedQueryStructure import org.neo4j.graphdb.config.Setting import org.neo4j.graphdb.factory.GraphDatabaseSettings import org.neo4j.logging.AssertableLogProvider.inLog @@ -51,11 +50,11 @@ class CypherCompilerAstCacheAcceptanceTest extends CypherFunSuite with GraphData errorIfShortestPathFallbackUsedAtRuntime = false, nonIndexedLabelWarningThreshold = 10000L ), - clock, GeneratedQueryStructure, + clock, new WrappedMonitors3_0(kernelMonitors), new StringInfoLogger3_0(log), plannerName = Some(IDPPlannerName), - runtimeName = Some(CompiledRuntimeName), + runtimeName = Some(InterpretedRuntimeName), updateStrategy = None, rewriterSequencer = RewriterStepSequencer.newValidating, publicTypeConverter = identity diff --git a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/v3_0/RuleExecutablePlanBuilderTest.scala b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/v3_0/RuleExecutablePlanBuilderTest.scala index d980c7ee86e5b..6199c274bba6f 100644 --- a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/v3_0/RuleExecutablePlanBuilderTest.scala +++ b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/v3_0/RuleExecutablePlanBuilderTest.scala @@ -44,7 +44,7 @@ import org.neo4j.cypher.internal.frontend.v3_0.ast.Statement import org.neo4j.cypher.internal.frontend.v3_0.test_helpers.CypherFunSuite import org.neo4j.cypher.internal.frontend.v3_0.{InternalException, Rewriter, Scope, SemanticTable} import org.neo4j.cypher.internal.spi.TransactionalContextWrapper -import org.neo4j.cypher.internal.spi.v3_0.{GeneratedQueryStructure, TransactionBoundQueryContext} +import org.neo4j.cypher.internal.spi.v3_0.TransactionBoundQueryContext import org.neo4j.graphdb.Label.label import org.neo4j.kernel.api.KernelTransaction import org.neo4j.kernel.api.security.AccessMode @@ -70,7 +70,7 @@ class RuleExecutablePlanBuilderTest queryPlanner = queryPlanner, rewriterSequencer = rewriterSequencer, plannerName = None, - runtimeBuilder = SilentFallbackRuntimeBuilder(InterpretedPlanBuilder(Clock.systemUTC(), mock[Monitors], identity), CompiledPlanBuilder(Clock.systemUTC(),GeneratedQueryStructure)), + runtimeBuilder = InterpretedRuntimeBuilder(InterpretedPlanBuilder(Clock.systemUTC(), mock[Monitors], identity)), semanticChecker = mock[SemanticChecker], updateStrategy = None, config = config, diff --git a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/CodeGeneratorTest.scala b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/CodeGeneratorTest.scala deleted file mode 100644 index 7fc3223cb9e7d..0000000000000 --- a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/CodeGeneratorTest.scala +++ /dev/null @@ -1,1085 +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.compiler.v3_0.codegen - -import java.time.Clock - -import org.mockito.Matchers._ -import org.mockito.Mockito._ -import org.mockito.invocation.InvocationOnMock -import org.mockito.stubbing.Answer -import org.neo4j.collection.primitive.PrimitiveLongIterator -import org.neo4j.cypher.internal.compiler.v3_0.executionplan.ExecutionPlanBuilder.tracer -import org.neo4j.cypher.internal.compiler.v3_0.executionplan.InternalExecutionResult -import org.neo4j.cypher.internal.compiler.v3_0.planner.LogicalPlanningTestSupport -import org.neo4j.cypher.internal.compiler.v3_0.planner.logical.plans._ -import org.neo4j.cypher.internal.compiler.v3_0.spi.{InternalResultRow, InternalResultVisitor, QueryContext} -import org.neo4j.cypher.internal.compiler.v3_0.{CostBasedPlannerName, NormalMode, TaskCloser} -import org.neo4j.cypher.internal.frontend.v3_0.ast._ -import org.neo4j.cypher.internal.frontend.v3_0.symbols._ -import org.neo4j.cypher.internal.frontend.v3_0.test_helpers.CypherFunSuite -import org.neo4j.cypher.internal.frontend.v3_0.{ParameterNotFoundException, SemanticDirection, SemanticTable} -import org.neo4j.cypher.internal.spi.TransactionalContextWrapper -import org.neo4j.cypher.internal.spi.v3_0.GeneratedQueryStructure -import org.neo4j.graphdb.{Direction, Node, Relationship} -import org.neo4j.kernel.api.ReadOperations -import org.neo4j.kernel.impl.api.RelationshipVisitor -import org.neo4j.kernel.impl.api.store.RelationshipIterator -import org.neo4j.kernel.impl.core.{NodeManager, NodeProxy, RelationshipProxy} - -import scala.collection.JavaConverters - -class CodeGeneratorTest extends CypherFunSuite with LogicalPlanningTestSupport { - - private val generator = new CodeGenerator(GeneratedQueryStructure) - - test("all nodes scan") { // MATCH a RETURN a - //given - val plan = ProduceResult(List("a"), AllNodesScan(IdName("a"), Set.empty)(solved)) - - //when - val compiled = compileAndExecute(plan) - - //then - val result = getNodesFromResult(compiled, "a") - result should equal(List( - Map("a" -> aNode), - Map("a" -> bNode), - Map("a" -> cNode), - Map("a" -> dNode), - Map("a" -> eNode), - Map("a" -> fNode), - Map("a" -> gNode), - Map("a" -> hNode), - Map("a" -> iNode))) - } - - test("label scan") {// MATCH (a:T1) RETURN a - //given - val plan = ProduceResult(List("a"), NodeByLabelScan(IdName("a"), lblName("T1"), Set.empty)(solved)) - - //when - val compiled = compileAndExecute(plan) - - //then - val result = getNodesFromResult(compiled, "a") - result should equal(List( - Map("a" -> aNode), - Map("a" -> bNode), - Map("a" -> cNode) - )) - } - - test("hash join of all nodes scans") { // MATCH a RETURN a - //given - val lhs = AllNodesScan(IdName("a"), Set.empty)(solved) - val rhs = AllNodesScan(IdName("a"), Set.empty)(solved) - val join = NodeHashJoin(Set(IdName("a")), lhs, rhs)(solved) - val plan = ProduceResult(List("a"), join) - - //when - val compiled = compileAndExecute(plan) - - //then - val result = getNodesFromResult(compiled, "a") - result should equal(List( - Map("a" -> aNode), - Map("a" -> bNode), - Map("a" -> cNode), - Map("a" -> dNode), - Map("a" -> eNode), - Map("a" -> fNode), - Map("a" -> gNode), - Map("a" -> hNode), - Map("a" -> iNode))) - } - - test("hash join on multiple keys") { - //given - val lhs = Expand(AllNodesScan(IdName("a"), Set.empty)(solved), IdName("a"), SemanticDirection.OUTGOING, Seq.empty, IdName("b"), IdName("r1"), ExpandAll)(solved) - val rhs = Expand(AllNodesScan(IdName("a"), Set.empty)(solved), IdName("a"), SemanticDirection.OUTGOING, Seq.empty, IdName("b"), IdName("r1"), ExpandAll)(solved) - val join = NodeHashJoin(Set(IdName("a"), IdName("b")), lhs, rhs)(solved) - val plan = ProduceResult(List("a"), join) - - //when - val compiled = compileAndExecute(plan) - - //then - val result = getNodesFromResult(compiled, "a") - result should equal(List( - Map("a" -> aNode), - Map("a" -> bNode), - Map("a" -> cNode), - Map("a" -> fNode), - Map("a" -> gNode), - Map("a" -> hNode), - Map("a" -> iNode) - )) - } - - test("cartesian product of two label scans") { - //given - val lhs = NodeByLabelScan(IdName("a"), lblName("T1"), Set.empty)(solved) - val rhs = NodeByLabelScan(IdName("b"), lblName("T2"), Set.empty)(solved) - val join = CartesianProduct(lhs, rhs)(solved) - val plan = ProduceResult(List("a", "b"), join) - - //when - val compiled = compileAndExecute(plan) - - //then - val result = getNodesFromResult(compiled, "a", "b") - result should equal(List( - Map("a" -> aNode, "b" -> fNode), - Map("a" -> aNode, "b" -> gNode), - Map("a" -> bNode, "b" -> fNode), - Map("a" -> bNode, "b" -> gNode), - Map("a" -> cNode, "b" -> fNode), - Map("a" -> cNode, "b" -> gNode))) - } - - test("all nodes scan + expand") { // MATCH (a)-[r]->(b) RETURN a, b - //given - val plan = ProduceResult(List("a", "b"), - Expand( - AllNodesScan(IdName("a"), Set.empty)(solved), IdName("a"), SemanticDirection.OUTGOING, Seq.empty, IdName("b"), IdName("r"), ExpandAll)(solved)) - - //when - val compiled = compileAndExecute(plan) - - //then - val result = getNodesFromResult(compiled, "a", "b") - - result should equal(List( - Map("a" -> aNode, "b" -> dNode), - Map("a" -> bNode, "b" -> dNode), - Map("a" -> cNode, "b" -> eNode), - Map("a" -> fNode, "b" -> dNode), - Map("a" -> gNode, "b" -> eNode), - Map("a" -> hNode, "b" -> iNode), - Map("a" -> iNode, "b" -> hNode))) - } - - test("label scan + expand outgoing") { // MATCH (a:T1)-[r]->(b) RETURN a, b - //given - val plan = ProduceResult(List("a", "b"), - Expand( - NodeByLabelScan(IdName("a"), lblName("T1"), Set.empty)(solved), IdName("a"), - SemanticDirection.OUTGOING, Seq.empty, IdName("b"), IdName("r"), ExpandAll)(solved)) - - //when - val compiled = compileAndExecute(plan) - - //then - val result = getNodesFromResult(compiled, "a", "b") - - result should equal(List( - Map("a" -> aNode, "b" -> dNode), - Map("a" -> bNode, "b" -> dNode), - Map("a" -> cNode, "b" -> eNode) - )) - } - - test("all node scan+ expand outgoing with one type") { // MATCH (a)-[r:R1]->(b) RETURN a, b - //given - val plan = ProduceResult(List("a", "b"), - Expand( - AllNodesScan(IdName("a"), Set.empty)(solved), IdName("a"), SemanticDirection.OUTGOING, Seq(RelTypeName("R1")(null)), IdName("b"), IdName("r"), ExpandAll)(solved)) - - //when - val compiled = compileAndExecute(plan) - - //then - val result = getNodesFromResult(compiled, "a", "b") - - result should equal(List( - Map("a" -> aNode, "b" -> dNode), - Map("a" -> bNode, "b" -> dNode), - Map("a" -> cNode, "b" -> eNode) - )) - } - - test("all node scan+ expand outgoing with multiple types") { // MATCH (a)-[r:R1|R2]->(b) RETURN a, b - //given - val plan = ProduceResult(List("a", "b"), - Expand( - AllNodesScan(IdName("a"), Set.empty)(solved), IdName("a"), SemanticDirection.OUTGOING, - Seq(RelTypeName("R1")(pos), RelTypeName("R2")(pos)), IdName("b"), IdName("r"), ExpandAll)(solved)) - - //when - val compiled = compileAndExecute(plan) - - //then - val result = getNodesFromResult(compiled, "a", "b") - - result should equal(List( - Map("a" -> aNode, "b" -> dNode), - Map("a" -> bNode, "b" -> dNode), - Map("a" -> cNode, "b" -> eNode), - Map("a" -> fNode, "b" -> dNode), - Map("a" -> gNode, "b" -> eNode))) - } - - test("label scan + expand incoming") { // // MATCH (a:T1)<-[r]-(b) RETURN a, b - //given - val plan = ProduceResult(List("a", "b"), - Expand( - NodeByLabelScan(IdName("a"), lblName("T1"), Set.empty)(solved), IdName("a"), - SemanticDirection.INCOMING, Seq.empty, IdName("b"), IdName("r"), ExpandAll)(solved)) - - //when - val compiled = compileAndExecute(plan) - - //then - val result = getNodesFromResult(compiled, "a", "b") - - result shouldBe empty - } - - test("label scan + optional expand incoming") { - //given - val plan = ProduceResult(List("a", "b"), - OptionalExpand( - NodeByLabelScan(IdName("a"), lblName("T1"), Set.empty)(solved), IdName("a"), - SemanticDirection.OUTGOING, Seq.empty, IdName("b"), IdName("r"), ExpandAll, - Seq(HasLabels(varFor("b"), Seq(LabelName("T1")(pos)))(pos)))(solved)) - - //when - val compiled: InternalExecutionResult = compileAndExecute(plan) - //then - val result = getNodesFromResult(compiled, "a", "b") - - result should equal(List( - Map("a" -> aNode, "b" -> null), - Map("a" -> bNode, "b" -> null), - Map("a" -> cNode, "b" -> null) - )) - } - - test("label scan + expand both directions") { // MATCH (a:T1)-[r]-(b) RETURN a, b - //given - val plan = ProduceResult(List("a", "b"), - Expand( - NodeByLabelScan(IdName("a"), lblName("T1"), Set.empty)(solved), IdName("a"), SemanticDirection.BOTH, - Seq.empty, IdName("b"), IdName("r"), ExpandAll)(solved)) - - //when - val compiled = compileAndExecute(plan) - - //then - val result = getNodesFromResult(compiled, "a", "b") - - result should equal(List( - Map("a" -> aNode, "b" -> dNode), - Map("a" -> bNode, "b" -> dNode), - Map("a" -> cNode, "b" -> eNode) - )) - } - - test("expand into on top of expand all") { - //given - val scanT1 = NodeByLabelScan(IdName("a"), lblName("T1"), Set.empty)(solved) - val expandAll = Expand( - scanT1, IdName("a"), SemanticDirection.OUTGOING, - Seq.empty, IdName("b"), IdName("r1"), ExpandAll)(solved) - val expandInto = Expand( - expandAll, IdName("b"), SemanticDirection.INCOMING, - Seq.empty, IdName("a"), IdName("r2"), ExpandInto)(solved) - - - val plan = ProduceResult(List("a", "b"), expandInto) - - //when - val compiled = compileAndExecute(plan) - - //then - val result = getNodesFromResult(compiled, "a", "b") - - result should equal(List( - Map("a" -> aNode, "b" -> dNode), - Map("a" -> bNode, "b" -> dNode), - Map("a" -> cNode, "b" -> eNode) - )) - } - - test("optional expand into on top of expand all") { - //given - val scanT1 = NodeByLabelScan(IdName("a"), lblName("T1"), Set.empty)(solved) - val expandAll = Expand( - scanT1, IdName("a"), SemanticDirection.OUTGOING, - Seq.empty, IdName("b"), IdName("r1"), ExpandAll)(solved) - val optionalExpandInto = OptionalExpand( - expandAll, IdName("a"), SemanticDirection.OUTGOING, - Seq.empty, IdName("b"), IdName("r2"), ExpandInto, Seq(HasLabels(varFor("b"), Seq(LabelName("T2")(pos)))(pos)))(solved) - - - val plan = ProduceResult(List("a", "b", "r2"), optionalExpandInto) - - //when - val compiled = compileAndExecute(plan) - - //then - val result = getResult(compiled, "a", "b", "r2") - - result should equal(List( - Map("a" -> aNode, "b" -> dNode, "r2" -> null), - Map("a" -> bNode, "b" -> dNode, "r2" -> null), - Map("a" -> cNode, "b" -> eNode, "r2" -> null) - )) - } - - test("expand into on top of expand all with relationship types") { - //given - val scanT2 = NodeByLabelScan(IdName("a"), lblName("T2"), Set.empty)(solved) - val expandAll = Expand( - scanT2, IdName("a"), SemanticDirection.OUTGOING, - Seq(RelTypeName("R2")(pos)), IdName("b"), IdName("r1"), ExpandAll)(solved) - val expandInto = Expand( - expandAll, IdName("b"), SemanticDirection.INCOMING, - Seq(RelTypeName("R2")(pos)), IdName("a"), IdName("r2"), ExpandInto)(solved) - - - val plan = ProduceResult(List("a", "b"), expandInto) - - //when - val compiled = compileAndExecute(plan) - - //then - val result = getNodesFromResult(compiled, "a", "b") - - result should equal(List( - Map("a" -> fNode, "b" -> dNode), - Map("a" -> gNode, "b" -> eNode) - )) - } - - test("optional expand into on top of expand all with relationship types") { - //given - val scanT2 = NodeByLabelScan(IdName("a"), lblName("T2"), Set.empty)(solved) - val expandAll = Expand( - scanT2, IdName("a"), SemanticDirection.OUTGOING, - Seq(RelTypeName("R2")(pos)), IdName("b"), IdName("r1"), ExpandAll)(solved) - val expandInto = OptionalExpand( - expandAll, IdName("b"), SemanticDirection.INCOMING, - Seq(RelTypeName("R2")(pos)), IdName("a"), IdName("r2"), ExpandInto)(solved) - - - val plan = ProduceResult(List("a", "b", "r2"), expandInto) - - //when - val compiled = compileAndExecute(plan) - - //then - val result = getResult(compiled, "a", "b", "r2") - - result should equal(List( - Map("a" -> fNode, "b" -> dNode, "r2" -> relMap(14L).relationship), - Map("a" -> gNode, "b" -> eNode, "r2" -> relMap(15L).relationship) - )) - } - - - test("expand into on top of expand all with a loop") { - //given - val scanT3 = NodeByLabelScan(IdName("a"), lblName("T3"), Set.empty)(solved) - val expandAll = Expand( - scanT3, IdName("a"), SemanticDirection.OUTGOING, - Seq(RelTypeName("R3")(pos)), IdName("b"), IdName("r1"), ExpandAll)(solved) - val expandInto = Expand( - expandAll, IdName("b"), SemanticDirection.INCOMING, - Seq(RelTypeName("R3")(pos)), IdName("a"), IdName("r2"), ExpandInto)(solved) - - - val plan = ProduceResult(List("a", "b"), expandInto) - - //when - val compiled = compileAndExecute(plan) - - //then - val result = getNodesFromResult(compiled, "a", "b") - - result should equal(List( - Map("a" -> hNode, "b" -> iNode), - Map("a" -> iNode, "b" -> hNode) - )) - } - - test("optional expand into on top of expand all with a loop") { - //given - val scanT3 = NodeByLabelScan(IdName("a"), lblName("T3"), Set.empty)(solved) - val expandAll = Expand( - scanT3, IdName("a"), SemanticDirection.OUTGOING, - Seq(RelTypeName("R3")(pos)), IdName("b"), IdName("r1"), ExpandAll)(solved) - val expandInto = OptionalExpand( - expandAll, IdName("b"), SemanticDirection.INCOMING, - Seq(RelTypeName("R3")(pos)), IdName("a"), IdName("r2"), ExpandInto, - Seq(HasLabels(varFor("b"), Seq(LabelName("T2")(pos)))(pos)))(solved) - - - val plan = ProduceResult(List("a", "b", "r2"), expandInto) - - //when - val compiled = compileAndExecute(plan) - - //then - val result = getResult(compiled, "a", "b", "r2") - - result should equal(List( - Map("a" -> hNode, "b" -> iNode, "r2" -> null), - Map("a" -> iNode, "b" -> hNode, "r2" -> null) - )) - } - - test("hash join on top of two expands from two all node scans") { - // MATCH (a)-[r1]->(b)<-[r2]-(c) RETURN a,b,c (kind of nothing enforcing that r1 and r2 are distinct) - - //given - val lhs = Expand(AllNodesScan(IdName("a"), Set.empty)(solved), IdName("a"), SemanticDirection.OUTGOING, Seq.empty, IdName("b"), IdName("r1"), ExpandAll)(solved) - val rhs = Expand(AllNodesScan(IdName("c"), Set.empty)(solved), IdName("c"), SemanticDirection.OUTGOING, Seq.empty, IdName("b"), IdName("r2"), ExpandAll)(solved) - val plan = ProduceResult(List("a", "b", "c"), NodeHashJoin(Set(IdName("b")), lhs, rhs)(solved)) - - val compiled = compileAndExecute(plan) - - //then - val result = getNodesFromResult(compiled, "a", "b", "c") - - result.toSet should equal(Set( - Map("a" -> aNode, "b" -> dNode, "c" -> fNode), - Map("a" -> aNode, "b" -> dNode, "c" -> bNode), - Map("a" -> aNode, "b" -> dNode, "c" -> aNode), - Map("a" -> bNode, "b" -> dNode, "c" -> aNode), - Map("a" -> bNode, "b" -> dNode, "c" -> bNode), - Map("a" -> bNode, "b" -> dNode, "c" -> fNode), - Map("a" -> fNode, "b" -> dNode, "c" -> aNode), - Map("a" -> fNode, "b" -> dNode, "c" -> bNode), - Map("a" -> fNode, "b" -> dNode, "c" -> fNode), - Map("a" -> cNode, "b" -> eNode, "c" -> cNode), - Map("a" -> cNode, "b" -> eNode, "c" -> gNode), - Map("a" -> gNode, "b" -> eNode, "c" -> cNode), - Map("a" -> gNode, "b" -> eNode, "c" -> gNode), - Map("a" -> hNode, "b" -> iNode, "c" -> hNode), - Map("a" -> iNode, "b" -> hNode, "c" -> iNode) - )) - } - - test("hash join on top of two expands from two label scans") { - // MATCH (a:T1)-[r1]->(b)<-[r2]-(c:T2) RETURN b - - //given - val lhs = Expand(NodeByLabelScan(IdName("a"), lblName("T1"), Set.empty)(solved), IdName("a"), - SemanticDirection.OUTGOING, Seq.empty, IdName("b"), IdName("r1"), ExpandAll)(solved) - val rhs = Expand(NodeByLabelScan(IdName("c"), lblName("T2"), Set.empty)(solved), IdName("c"), - SemanticDirection.OUTGOING, Seq.empty, IdName("b"), IdName("r2"), ExpandAll)(solved) - val join = NodeHashJoin(Set(IdName("b")), lhs, rhs)(solved) - val plan = ProduceResult(List("a", "b", "c"), join) - - val compiled = compileAndExecute(plan) - - //then - val result = getNodesFromResult(compiled, "a", "b", "c") - - result.toSet should equal(Set( - Map("a" -> aNode, "b" -> dNode, "c" -> fNode), - Map("a" -> bNode, "b" -> dNode, "c" -> fNode), - Map("a" -> cNode, "b" -> eNode, "c" -> gNode) - )) - } - - - test("hash join on top of hash join") { - - //given - val scan1 = NodeByLabelScan(IdName("a"), lblName("T1"), Set.empty)(solved) - val scan2 = NodeByLabelScan(IdName("a"), lblName("T1"), Set.empty)(solved) - val scan3 = NodeByLabelScan(IdName("a"), lblName("T1"), Set.empty)(solved) - val join1 = NodeHashJoin(Set(IdName("a")), scan1, scan2)(solved) - val join2 = NodeHashJoin(Set(IdName("a")), scan3, join1)(solved) - val projection = Projection(join2, Map("a" -> varFor("a")))(solved) - val plan = ProduceResult(List("a"), projection) - - val compiled = compileAndExecute(plan) - - //then - val result = getNodesFromResult(compiled, "a") - - result.toSet should equal(Set( - Map("a" -> aNode), - Map("a" -> bNode), - Map("a" -> cNode) - )) - } - - test("project literal") { - val plan = ProduceResult(List("a"), Projection(SingleRow()(solved), Map("a" -> SignedDecimalIntegerLiteral("1")(pos)))(solved)) - val compiled = compileAndExecute(plan) - - //then - val result = getResult(compiled, "a") - result.toSet should equal(Set(Map("a" -> 1))) - } - - test("project parameter") { - - val plan = ProduceResult(List("a"), Projection(SingleRow()(solved), Map("a" -> Parameter("FOO", CTAny)(pos)))(solved)) - val compiled = compileAndExecute(plan, Map("FOO" -> "BAR")) - - //then - val result = getResult(compiled, "a") - result.toSet should equal(Set(Map("a" -> "BAR"))) - } - - test("project addition of two ints") { - val lhs = SignedDecimalIntegerLiteral("1")(pos) - val rhs = SignedDecimalIntegerLiteral("3")(pos) - val add = Add(lhs, rhs)(pos) - - val plan = ProduceResult(List("a"), Projection(SingleRow()(solved), Map("a" -> add))(solved)) - val compiled = compileAndExecute(plan) - - //then - val result = getResult(compiled, "a") - result.toSet should equal(Set(Map("a" -> 4))) - } - - test("project subtraction of two ints") { - val lhs = SignedDecimalIntegerLiteral("7")(pos) - val rhs = SignedDecimalIntegerLiteral("5")(pos) - val subtract = Subtract(lhs, rhs)(pos) - - val plan = ProduceResult(List("a"), Projection(SingleRow()(solved), Map("a" -> subtract))(solved)) - val compiled = compileAndExecute(plan) - - //then - val result = getResult(compiled, "a") - result.toSet should equal(Set(Map("a" -> 2))) - } - - test("project addition of int and double") { - val lhs = SignedDecimalIntegerLiteral("1")(pos) - val rhs = DecimalDoubleLiteral("3.0")(pos) - val add = Add(lhs, rhs)(pos) - - val plan = ProduceResult(List("a"), Projection(SingleRow()(solved), Map("a" -> add))(solved)) - val compiled = compileAndExecute(plan) - - //then - val result = getResult(compiled, "a") - result.toSet should equal(Set(Map("a" -> (1L + 3.0)))) - } - - test("project addition of int and String") { - val lhs = SignedDecimalIntegerLiteral("1")(pos) - val rhs = StringLiteral("two")(pos) - val add = Add(lhs, rhs)(pos) - - val plan = ProduceResult(List("a"), Projection(SingleRow()(solved), Map("a" -> add))(solved)) - val compiled = compileAndExecute(plan) - - //then - val result = getResult(compiled, "a") - result.toSet should equal(Set(Map("a" -> "1two"))) - } - - test("project addition of int and value from params") { - val lhs = SignedDecimalIntegerLiteral("1")(pos) - val rhs = Parameter("FOO", CTAny)(pos) - val add = Add(lhs, rhs)(pos) - val plan = ProduceResult(List("a"), Projection(SingleRow()(solved), Map("a" -> add))(solved)) - val compiled = compileAndExecute(plan, Map("FOO" -> Long.box(3L))) - - //then - val result = getResult(compiled, "a") - result.toSet should equal(Set(Map("a" -> 4))) - } - - test("project addition of two values coming from params") { - val lhs = Parameter("FOO", CTAny)(pos) - val rhs = Parameter("BAR", CTAny)(pos) - val add = Add(lhs, rhs)(pos) - val plan = ProduceResult(List("a"), Projection(SingleRow()(solved), Map("a" -> add))(solved)) - val compiled = compileAndExecute(plan, Map("FOO" -> Long.box(3L), "BAR" -> Long.box(1L))) - - //then - val result = getResult(compiled, "a") - result.toSet should equal(Set(Map("a" -> 4))) - } - - test("project collection") { - val collection = Collection(Seq(Parameter("FOO", CTAny)(pos), Parameter("BAR", CTAny)(pos)))(pos) - val plan = ProduceResult(List("a"), Projection(SingleRow()(solved), Map("a" -> collection))(solved)) - val compiled = compileAndExecute(plan, Map("FOO" -> Long.box(3L), "BAR" -> Long.box(1L))) - - //then - val result = getResult(compiled, "a") - result.toSet should equal(Set(Map("a" -> List(3, 1)))) - } - - test("project map") { - val map = MapExpression(Seq((PropertyKeyName("FOO")(pos), Parameter("BAR", CTAny)(pos))))(pos) - val plan = ProduceResult(List("a"), Projection(SingleRow()(solved), Map("a" -> map))(solved)) - val compiled = compileAndExecute(plan, Map("FOO" -> Long.box(3L), "BAR" -> Long.box(1L))) - - //then - val result = getResult(compiled, "a") - result.toSet should equal(Set(Map("a" -> Map("FOO" -> 1)))) - } - - test("string equality") { - val equals = Equals(StringLiteral("a string")(pos), StringLiteral("a string")(pos))(pos) - val plan = ProduceResult(List("result"), Projection(SingleRow()(solved), Map("result" -> equals))(solved)) - val compiled = compileAndExecute(plan) - - //then - val result = getResult(compiled, "result") - result.toSet should equal(Set(Map("result" -> true))) - } - - test("number equality, double and long") { - val equals = Equals(SignedDecimalIntegerLiteral("9007199254740993")(pos), DecimalDoubleLiteral("9007199254740992")(pos))(pos) - val plan = ProduceResult(List("result"), Projection(SingleRow()(solved), Map("result" -> equals))(solved)) - val compiled = compileAndExecute(plan) - - //then - val result = getResult(compiled, "result") - result.toSet should equal(Set(Map("result" -> false))) - } - - test("number equality, one from parameter") { - val equals = Equals(SignedDecimalIntegerLiteral("9007199254740993")(pos), Parameter("BAR", CTAny)(pos))(pos) - val plan = ProduceResult(List("result"), Projection(SingleRow()(solved), Map("result" -> equals))(solved)) - val compiled = compileAndExecute(plan, Map("BAR" -> Double.box(9007199254740992D))) - - val result = getResult(compiled, "result") - result.toSet should equal(Set(Map("result" -> false))) - } - - test("or between two literal booleans") { - val or = Or(True()(pos), False()(pos))(pos) - val plan = ProduceResult(List("result"), Projection(SingleRow()(solved), Map("result" -> or))(solved)) - val compiled = compileAndExecute(plan) - - //then - val result = getResult(compiled, "result") - result.toSet should equal(Set(Map("result" -> true))) - } - - test("or one from parameter") { - val or = Or(False()(pos), Parameter("FOO", CTAny)(pos))(pos) - val plan = ProduceResult(List("result"), Projection(SingleRow()(solved), Map("result" -> or))(solved)) - val compiled = compileAndExecute(plan, Map("FOO" -> Boolean.box(false))) - - //then - val result = getResult(compiled, "result") - result.toSet should equal(Set(Map("result" -> false))) - } - - test("or two from parameter, one null") { - val or = Or(Parameter("FOO", CTAny)(pos), Parameter("BAR", CTAny)(pos))(pos) - val plan = ProduceResult(List("result"), Projection(SingleRow()(solved), Map("result" -> or))(solved)) - val compiled = compileAndExecute(plan, Map("FOO" -> Boolean.box(true), "BAR" -> null)) - - //then - val result = getResult(compiled, "result") - result.toSet should equal(Set(Map("result" -> true))) - } - - test("or two from parameter, both null") { - val or = Or(Parameter("FOO", CTAny)(pos), Parameter("BAR", CTAny)(pos))(pos) - val plan = ProduceResult(List("result"), Projection(SingleRow()(solved), Map("result" -> or))(solved)) - val compiled = compileAndExecute(plan, Map("FOO" -> null, "BAR" -> null)) - - //then - val result = getResult(compiled, "result") - result.toSet should equal(Set(Map("result" -> null))) - } - - test("not on a literal") { - val not = Not(False()(pos))(pos) - val plan = ProduceResult(List("result"), Projection(SingleRow()(solved), Map("result" -> not))(solved)) - val compiled = compileAndExecute(plan) - - //then - val result = getResult(compiled, "result") - result.toSet should equal(Set(Map("result" -> true))) - } - - test("not on a parameter") { - val not = Not(Parameter("FOO", CTAny)(pos))(pos) - val plan = ProduceResult(List("result"), Projection(SingleRow()(solved), Map("result" -> not))(solved)) - val compiled = compileAndExecute(plan, Map("FOO" -> Boolean.box(false))) - - //then - val result = getResult(compiled, "result") - result.toSet should equal(Set(Map("result" -> true))) - } - - test("not on a null parameter") { - val not = Not(Parameter("FOO", CTAny)(pos))(pos) - val plan = ProduceResult(List("result"), Projection(SingleRow()(solved), Map("result" -> not))(solved)) - val compiled = compileAndExecute(plan, Map("FOO" -> null)) - - //then - val result = getResult(compiled, "result") - result.toSet should equal(Set(Map("result" -> null))) - } - - test("close transaction after successfully exhausting result") { - // given - val plan = ProduceResult(List("a"), Projection(SingleRow()(solved), Map("a" -> SignedDecimalIntegerLiteral("1")(null)))(solved)) - - // when - val closer = mock[TaskCloser] - val compiled = compileAndExecute(plan, taskCloser = closer) - - // then - verifyZeroInteractions(closer) - val visitor = mock[InternalResultVisitor[RuntimeException]] - when(visitor.visit(any[InternalResultRow])).thenReturn(true) - compiled.accept(visitor) - verify(closer).close(success = true) - } - - test("close transaction after prematurely terminating result exhaustion") { - // given - val plan = ProduceResult(List("a"), Projection(SingleRow()(solved), Map("a" -> SignedDecimalIntegerLiteral("1")(null)))(solved)) - - // when - val closer = mock[TaskCloser] - val compiled = compileAndExecute(plan, taskCloser = closer) - - // then - verifyZeroInteractions(closer) - val visitor = mock[InternalResultVisitor[RuntimeException]] - when(visitor.visit(any[InternalResultRow])).thenReturn(false) - compiled.accept(visitor) - verify(closer).close(success = true) - } - - test("close transaction after failure while handling results") { - // given - val plan = ProduceResult(List("a"), Projection(SingleRow()(solved), Map("a" -> SignedDecimalIntegerLiteral("1")(null)))(solved)) - - // when - val closer = mock[TaskCloser] - val compiled = compileAndExecute( plan, taskCloser = closer ) - - // then - verifyZeroInteractions(closer) - val visitor = mock[InternalResultVisitor[RuntimeException]] - val exception = new scala.RuntimeException() - when(visitor.visit(any[InternalResultRow])).thenThrow(exception) - intercept[RuntimeException] { - compiled.accept(visitor) - - } - verify(closer).close(success = false) - } - - test("should throw the same error as the user provides") { - // given - val plan = ProduceResult(List("a"), Projection(SingleRow()(solved), Map("a" -> SignedDecimalIntegerLiteral("1")(null)))(solved)) - - // when - val closer = mock[TaskCloser] - val compiled = compileAndExecute( plan, taskCloser = closer ) - - // then - val visitor = mock[InternalResultVisitor[RuntimeException]] - val exception = new scala.RuntimeException() - when(visitor.visit(any[InternalResultRow])).thenThrow(exception) - try { - compiled.accept(visitor) - fail("should have thrown error") - } - catch { - case e: Throwable => e should equal(exception) - } - - } - - test("throw error when parameter is missing") { - //given - val plan = ProduceResult(List("a"), Projection(SingleRow()(solved), Map("a" -> Parameter("FOO", CTAny)(pos)))(solved)) - - //when - val compiled = compileAndExecute(plan) - - //then - intercept[ParameterNotFoundException](getResult(compiled, "a")) - } - - test("handle line breaks and double quotes in names") { - //given - val name = """{"a": - |1 - |} - """.stripMargin - val plan = ProduceResult(List(name), Projection(SingleRow()(solved), - Map(name -> SignedDecimalIntegerLiteral("1")(pos)))(solved)) - - //when - val compiled = compileAndExecute(plan, Map("FOO" -> Long.box(3L), "BAR" -> Long.box(1L))) - - //then - val result = getResult(compiled, name) - result.toSet should equal(Set(Map(name -> 1))) - } - - private def compile(plan: LogicalPlan) = { - generator.generate(plan, newMockedPlanContext, Clock.systemUTC(), semanticTable, CostBasedPlannerName.default) - } - - private def compileAndExecute(plan: LogicalPlan, params: Map[String, AnyRef] = Map.empty, taskCloser: TaskCloser = new TaskCloser) = { - compile(plan).executionResultBuilder(queryContext, NormalMode, tracer(NormalMode), params, taskCloser) - } - - /* - * Mocks the following graph: - * - * (a:T1) -[:R1] ->(d)<-[:R2]-(f:T2) - * ↗ - * (b:T1) -[:R1] - * - * (c:T1) -[:R1] ->(e)<-[:R2]-(g:T2) - * - * (h:T3)-(t2:T3)-(g:T3) - * - */ - private val labelTokens = Map("T1" -> 1, "T2" -> 2, "T3" -> 3) - private val relTokens = Map("R1" -> 1, "R2" -> 2, "R3" -> 3) - - private val aNode = mockNode(0L, "a") - private val bNode = mockNode(1L, "b") - private val cNode = mockNode(2L, "c") - private val dNode = mockNode(3L, "d") - private val eNode = mockNode(4L, "e") - private val fNode = mockNode(5L, "f") - private val gNode = mockNode(6L, "g") - private val hNode = mockNode(7L, "h") - private val iNode = mockNode(8L, "i") - - private val semanticTable = mock[SemanticTable] - when(semanticTable.isNode(varFor("a"))).thenReturn(true) - when(semanticTable.isNode(varFor("b"))).thenReturn(true) - when(semanticTable.isNode(varFor("c"))).thenReturn(true) - when(semanticTable.isNode(varFor("d"))).thenReturn(true) - when(semanticTable.isNode(varFor("e"))).thenReturn(true) - when(semanticTable.isNode(varFor("f"))).thenReturn(true) - when(semanticTable.isNode(varFor("g"))).thenReturn(true) - when(semanticTable.isNode(varFor("h"))).thenReturn(true) - when(semanticTable.isNode(varFor("i"))).thenReturn(true) - when(semanticTable.isRelationship(varFor("r1"))).thenReturn(true) - when(semanticTable.isRelationship(varFor("r2"))).thenReturn(true) - - private val allNodes = Seq(aNode, bNode, cNode, dNode, eNode, fNode, gNode, hNode, iNode) - private val nodesForLabel = Map("T1" -> Seq(aNode, bNode, cNode), "T2" -> Seq(fNode, gNode), "T3" -> Seq(hNode, iNode)) - - private val relMap = Map( - 11L -> RelationshipData(aNode, dNode, 11L, 1), - 12L -> RelationshipData(bNode, dNode, 12L, 1), - 13L -> RelationshipData(cNode, eNode, 13L, 1), - 14L -> RelationshipData(fNode, dNode, 14L, 2), - 15L -> RelationshipData(gNode, eNode, 15L, 2), - 16L -> RelationshipData(hNode, iNode, 16L, 3), - 17L -> RelationshipData(iNode, hNode, 17L, 3)) - - val nodeManager = mock[NodeManager] - when(nodeManager.newNodeProxyById(anyLong())).thenAnswer(new Answer[Node]() { - override def answer(invocationOnMock: InvocationOnMock): NodeProxy = { - val id = invocationOnMock.getArguments.apply(0).asInstanceOf[Long].toInt - allNodes(id) - } - }) - when(nodeManager.newRelationshipProxyById(anyLong())).thenAnswer(new Answer[Relationship]() { - override def answer(invocationOnMock: InvocationOnMock): RelationshipProxy = { - val id = invocationOnMock.getArguments.apply(0).asInstanceOf[Long].toInt - relMap(id).relationship - } - }) - - private val queryContext = mock[QueryContext] - private val transactionalContext = mock[TransactionalContextWrapper] - private val ro = mock[ReadOperations] - when(queryContext.transactionalContext).thenReturn(transactionalContext) - when(transactionalContext.readOperations).thenReturn(ro) - when(queryContext.entityAccessor).thenReturn(nodeManager.asInstanceOf[queryContext.EntityAccessor]) - when(ro.nodesGetAll()).thenAnswer(new Answer[PrimitiveLongIterator] { - override def answer(invocationOnMock: InvocationOnMock): PrimitiveLongIterator = primitiveIterator(allNodes.map(_.getId)) - }) - when(ro.labelGetForName(anyString())).thenAnswer(new Answer[Int] { - override def answer(invocationOnMock: InvocationOnMock): Int = { - val label = invocationOnMock.getArguments.apply(0).asInstanceOf[String] - labelTokens(label) - } - }) - when(ro.relationshipTypeGetForName(anyString())).thenAnswer(new Answer[Int] { - override def answer(invocationOnMock: InvocationOnMock): Int = { - val label = invocationOnMock.getArguments.apply(0).asInstanceOf[String] - relTokens(label) - } - }) - when(ro.nodesGetForLabel(anyInt())).thenAnswer(new Answer[PrimitiveLongIterator] { - override def answer(invocationOnMock: InvocationOnMock): PrimitiveLongIterator = { - val labelToken = invocationOnMock.getArguments.apply(0).asInstanceOf[Int] - val (label, _) = labelTokens.find { - case (l, t) => t == labelToken - }.get - val nodeIds = nodesForLabel(label).map(_.getId) - primitiveIterator(nodeIds) - } - }) - when(ro.nodeGetRelationships(anyLong(), any[Direction])).thenAnswer(new Answer[PrimitiveLongIterator] { - override def answer(invocationOnMock: InvocationOnMock): PrimitiveLongIterator = { - val node = invocationOnMock.getArguments.apply(0).asInstanceOf[Long].toInt - val dir = invocationOnMock.getArguments.apply(1).asInstanceOf[Direction] - getRelsForNode(allNodes(node), dir, Set.empty) - } - }) - when(ro.nodeGetRelationships(anyLong(), any[Direction], anyVararg[Int]())).thenAnswer(new Answer[PrimitiveLongIterator] { - override def answer(invocationOnMock: InvocationOnMock): PrimitiveLongIterator = { - val arguments = invocationOnMock.getArguments - val node = arguments(0).asInstanceOf[Long].toInt - val dir = arguments(1).asInstanceOf[Direction] - val types = (2 until arguments.length).map(arguments(_).asInstanceOf[Int]).toSet - getRelsForNode(allNodes(node), dir, types) - } - }) - when(ro.relationshipVisit(anyLong(), any())).thenAnswer(new Answer[Unit] { - override def answer(invocationOnMock: InvocationOnMock): Unit = { - val relId = invocationOnMock.getArguments.apply(0).asInstanceOf[Long] - val visitor = invocationOnMock.getArguments.apply(1).asInstanceOf[RelationshipVisitor[_]] - val rel = relMap(relId) - visitor.visit(relId, -1, rel.from.getId, rel.to.getId) - } - }) - when(ro.nodeGetDegree(anyLong(), any())).thenReturn(1) - when(ro.nodeGetDegree(anyLong(), any(), anyInt())).thenReturn(1) - when(ro.nodeHasLabel(anyLong(), anyInt())).thenAnswer(new Answer[Boolean] { - override def answer(invocationOnMock: InvocationOnMock) = { - val nodeId = invocationOnMock.getArguments.apply(0).asInstanceOf[Long] - val labelId = invocationOnMock.getArguments.apply(1).asInstanceOf[Int] - val label = labelTokens.map { - case (labelName, t) if t == labelId => Some(labelName) - case _ => None - }.head - label.exists(l => nodesForLabel.contains(l) && nodesForLabel(l).exists(_.getId == nodeId) - ) - } - }) - - private def mockNode(id: Long, name: String) = { - val node = mock[NodeProxy] - when(node.getId).thenReturn(id) - when(node.toString).thenReturn(name) - node - } - - private def mockRelationship(relationshipData: RelationshipData) = { - val rel = mock[RelationshipProxy] - val toStringValue = relationshipData.toString - when(rel.getId).thenReturn(relationshipData.id) - when(rel.getStartNode).thenReturn(relationshipData.from) - when(rel.getEndNode).thenReturn(relationshipData.to) - when(rel.toString).thenReturn(toStringValue) - rel - } - - private def getRelsForNode(node: Node, dir: Direction, types: Set[Int]) = { - def hasType(relationship: RelationshipData) = types.isEmpty || types(relationship.relType) - if (dir == Direction.OUTGOING) { - val relIds = relMap.values.filter(n => n.from == node && hasType(n)).map(_.id).toSeq - relationshipIterator(relIds) - } else if (dir == Direction.INCOMING) { - val relIds = relMap.values.filter(n => n.to == node && hasType(n)).map(_.id).toSeq - relationshipIterator(relIds) - } else { - val relIds = relMap.values.filter(n => (n.from == node || n.to == node) && hasType(n)).map(_.id).toSeq - relationshipIterator(relIds) - } - } - - case class RelationshipData(from: Node, to: Node, id: Long, relType: Int) { - val relationship = mockRelationship(this) - - override def toString: String = s"($from)-[$relType]->($to)" - } - - private def primitiveIterator(longs: Seq[Long]) = new PrimitiveLongIterator { - val inner = longs.toIterator - - override def next(): Long = inner.next() - - override def hasNext: Boolean = inner.hasNext - } - - private def relationshipIterator(longs: Seq[Long]) = new RelationshipIterator { - - override def relationshipVisit[EXCEPTION <: Exception](relationshipId: Long, visitor: RelationshipVisitor[EXCEPTION]): Boolean = { - val rel = relMap(relationshipId) - visitor.visit(relationshipId, -1, rel.from.getId, rel.to.getId) - false - } - - val inner = longs.toIterator - - override def next(): Long = inner.next() - - override def hasNext: Boolean = inner.hasNext - } - - private def getNodesFromResult(plan: InternalExecutionResult, columns: String*) = { - val res = Seq.newBuilder[Map[String, Node]] - - plan.accept(new InternalResultVisitor[RuntimeException]() { - override def visit(element: InternalResultRow): Boolean = { - res += columns.map(col => col -> element.getNode(col)).toMap - true - } - }) - res.result() - } - - private def getResult(plan: InternalExecutionResult, columns: String*) = { - val res = Seq.newBuilder[Map[String, Any]] - - plan.accept(new InternalResultVisitor[RuntimeException]() { - override def visit(element: InternalResultRow): Boolean = { - res += columns.map(col => col -> element.get(col)).toMap - true - } - }) - res.result().asComparableResult - } - - - implicit class RichMapSeq(res: Seq[Map[String, Any]]) { - import JavaConverters._ - - def asComparableResult: Seq[Map[String, Any]] = res.map((map: Map[String, Any]) => - map.map { - case (k, a: Array[_]) => k -> a.toList - case (k, a: java.util.List[_]) => k -> a.asScala - case (k, m: java.util.Map[_,_]) => k -> m.asScala - case m => m - } - ) - } - -} diff --git a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/BuildProbeTableInstructionsTest.scala b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/BuildProbeTableInstructionsTest.scala deleted file mode 100644 index c270141631f9d..0000000000000 --- a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/BuildProbeTableInstructionsTest.scala +++ /dev/null @@ -1,200 +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.compiler.v3_0.codegen.ir - -import java.util.concurrent.atomic.AtomicInteger - -import org.mockito.Mockito._ -import org.mockito.invocation.InvocationOnMock -import org.mockito.stubbing.Answer -import org.neo4j.collection.primitive.PrimitiveLongIterator -import org.neo4j.cypher.internal.compiler.v3_0.codegen.{CodeGenContext, JoinTableMethod, Variable} -import org.neo4j.cypher.internal.compiler.v3_0.spi.QueryContext -import org.neo4j.cypher.internal.frontend.v3_0.test_helpers.CypherFunSuite -import org.neo4j.cypher.internal.frontend.v3_0.{SemanticTable, symbols} -import org.neo4j.cypher.internal.spi.TransactionalContextWrapper -import org.neo4j.graphdb.Node -import org.neo4j.kernel.api.ReadOperations -import org.neo4j.kernel.impl.core.{NodeManager, NodeProxy} - -import scala.collection.mutable - -class BuildProbeTableInstructionsTest extends CypherFunSuite with CodeGenSugar { - - private val tableVarName = "probeTable" - private val buildTableMethodName = "buildProbeTable" - private val resultRowKey = "resultKey" - - private val entityAccessor = mock[NodeManager] - private val queryContext = mock[QueryContext] - private val transactionalContext = mock[TransactionalContextWrapper] - private val readOps = mock[ReadOperations] - private val allNodeIds = mutable.ArrayBuffer[Long]() - - // used by instructions that generate probe tables - private implicit val codeGenContext = new CodeGenContext(SemanticTable(), Map.empty) - when(queryContext.transactionalContext).thenReturn(transactionalContext) - when(transactionalContext.readOperations).thenReturn(readOps) - when(queryContext.entityAccessor).thenReturn(entityAccessor.asInstanceOf[queryContext.EntityAccessor]) - when(readOps.nodesGetAll()).then(new Answer[PrimitiveLongIterator] { - def answer(invocation: InvocationOnMock) = allNodeIdsIterator() - }) - - override protected def beforeEach() = allNodeIds.clear() - - test("should generate correct code for simple counting probe table") { - // Given - setUpNodeMocks(1, 2, 42) - val nodeVar = "node" - val nodes = Set(Variable(nodeVar, symbols.CTNode)) - - val buildInstruction = BuildCountingProbeTable(id = "countingTable", - name = tableVarName, - nodes = nodes) - - // When - val results = runTest(buildInstruction, nodes) - - // Then - results should have size 3 - val (a :: b :: c :: Nil) = results - checkNodeResult(1, a) - checkNodeResult(2, b) - checkNodeResult(42, c) - } - - test("should generate correct code for a counting probe table on multiple keys") { - // Given - setUpNodeMocks(1, 2) - val nodes = Set(Variable("node1", symbols.CTNode), Variable("node2", symbols.CTNode)) - val buildInstruction = BuildCountingProbeTable(id = "countingTable", - name = tableVarName, - nodes = nodes) - - // When - val results = runTest(buildInstruction, nodes) - - // Then - results should have size 4 - val (a :: b :: c :: d :: Nil) = results - checkNodeResult(1, a) - checkNodeResult(1, b) - checkNodeResult(2, c) - checkNodeResult(2, d) - } - - test("should generate correct code for simple recording probe table") { - // Given - setUpNodeMocks(42, 4242) - val nodeVar = "node" - val nodes = Set(Variable(nodeVar, symbols.CTNode)) - val buildInstruction = BuildRecordingProbeTable(id = "recordingTable", - name = tableVarName, - nodes = nodes, - valueSymbols = Map(nodeVar -> Variable(nodeVar, symbols.CTNode))) - - // When - val results = runTest(buildInstruction, nodes) - - // Then - results should have size 2 - val (a :: b :: Nil) = results - checkNodeResult(42, a) - checkNodeResult(4242, b) - } - - test("should generate correct code for recording probe table on multiple keys") { - // Given - setUpNodeMocks(42, 4242) - val joinNodes = Set(Variable("node1", symbols.CTNode), Variable("node2", symbols.CTNode)) - val buildInstruction = BuildRecordingProbeTable(id = "recordingTable", - name = tableVarName, - nodes = joinNodes, - valueSymbols = Map("node1" -> Variable("node1", symbols.CTNode))) - - // When - val results = runTest(buildInstruction, joinNodes) - - // Then - results should have size 4 - val (a :: b :: c:: d :: Nil) = results - checkNodeResult(42, a) - checkNodeResult(42, b) - checkNodeResult(4242, c) - checkNodeResult(4242, d) - } - - private def setUpNodeMocks(ids: Long*): Unit = { - ids.foreach { id => - val nodeMock = mock[NodeProxy] - when(nodeMock.getId).thenReturn(id) - when(entityAccessor.newNodeProxyById(id)).thenReturn(nodeMock) - allNodeIds += id - } - } - - private def checkNodeResult(id: Long, res: Map[String, Object]): Unit = { - res.size shouldEqual 1 - val node = res(resultRowKey).asInstanceOf[Node] - node.getId shouldEqual id - } - - private def allNodeIdsIterator() = new PrimitiveLongIterator { - val inner = allNodeIds.iterator - - override def hasNext = inner.hasNext - - override def next() = inner.next() - } - - private def runTest(buildInstruction: BuildProbeTable, nodes: Set[Variable]): List[Map[String, Object]] = { - val instructions = buildProbeTableWithTwoAllNodeScans(buildInstruction, nodes) - val ids = instructions.flatMap(_.allOperatorIds.map(id => id -> null)).toMap - evaluate(instructions, queryContext, Seq(resultRowKey), Map.empty[String, Object], ids) - } - - private def buildProbeTableWithTwoAllNodeScans(buildInstruction: BuildProbeTable, nodes: Set[Variable]): Seq[Instruction] = { - val counter = new AtomicInteger(0) - val buildWhileLoop = nodes.foldRight[Instruction](buildInstruction){ - case (variable, instruction) => WhileLoop(variable, ScanAllNodes("scanOp" + counter.incrementAndGet()), instruction) - } - - val buildProbeTableMethod = MethodInvocation(operatorId = Set.empty, - symbol = JoinTableMethod(tableVarName, buildInstruction.tableType), - methodName = buildTableMethodName, - statements = Seq(buildWhileLoop)) - - val probeVars = nodes.map(n => n.copy(name = s"probe" + n.name)) - //just put one node in the actual result - val resultVar = probeVars.head - - val acceptVisitor = AcceptVisitor("visitorOp", Map(resultRowKey -> expressions.NodeProjection(resultVar))) - - val probeTheTable = GetMatchesFromProbeTable(keys = probeVars, - code = buildInstruction.joinData, - action = acceptVisitor) - - val probeTheTableWhileLoop = probeVars.foldRight[Instruction](probeTheTable){ - case (variable, instruction) => WhileLoop(variable, ScanAllNodes("scanOp" + counter.incrementAndGet()), instruction) - } - Seq(buildProbeTableMethod, probeTheTableWhileLoop) - } - -} diff --git a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/CodeGenExpressionCompilationTest.scala b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/CodeGenExpressionCompilationTest.scala deleted file mode 100644 index c9a199aea630d..0000000000000 --- a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/CodeGenExpressionCompilationTest.scala +++ /dev/null @@ -1,162 +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.compiler.v3_0.codegen.ir - -import org.neo4j.cypher.internal.compiler.v3_0.codegen.ir.expressions._ -import org.neo4j.cypher.internal.frontend.v3_0 -import org.neo4j.cypher.internal.frontend.v3_0.CypherTypeException -import org.neo4j.cypher.internal.frontend.v3_0.test_helpers.CypherFunSuite -import org.scalatest._ - -class CodeGenExpressionCompilationTest extends CypherFunSuite with Matchers with CodeGenSugar { - - private val traceIds = Map("X" -> null, "id" -> null) - - case class Operation(name: String, - execute: (CodeGenExpression, CodeGenExpression) => CodeGenExpression, - data: Seq[(Any, Any, Either[Any, Class[_ <: Exception]])]) - - val addOperation = Operation("Addition", Addition.apply, Seq( - (7, 9, Left(16)), - ("abc", 7, Left("abc7")), - (9, "abc", Left("9abc")), - (3.14, "abc", Left("3.14abc")), - ("abc", 3.14, Left("abc3.14")), - (7, 3.14, Left(10.14)), - (11.6, 3, Left(14.6)), - (2.5, 4.5, Left(7.0)), - (Long.MaxValue, Long.MinValue, Left(-1)), - (42, null, Left(null)), - (null, 42, Left(null)), - (true, 3, Right(classOf[CypherTypeException]))) - ) - - val subOperation = Operation("Subtraction", Subtraction.apply, Seq( - (9, 7, Left(2)), - (Long.MaxValue, Int.MaxValue, Left(Long.MaxValue - Int.MaxValue)), - (3.25, 3, Left(0.25)), - (3.21, 1.23, Left(1.98)), - (-1, -2, Left(1)), - (-1.25, -2.5, Left(1.25)), - (2, null, Left(null)), - (null, 2, Left(null)), - (false, 3, Right(classOf[CypherTypeException]))) - ) - - val mulOperation = Operation("Multiplication", Multiplication.apply, Seq( - (0, 0, Left(0)), - (0, 42, Left(0)), - (1, 1, Left(1)), - (5, 20, Left(100)), - (2, -10, Left(-20)), - (-2, 10, Left(-20)), - (-2, -10, Left(20)), - (0.0, 0.0, Left(0.0)), - (0.0, 42.5, Left(0.0)), - (1.2, 1, Left(1.2)), - (5.0, 20.0, Left(100.0)), - (2.0, -10.0, Left(-20.0)), - (-2.0, 10.0, Left(-20.0)), - (-2.0, -10.0, Left(20.0)), - (null, null, Left(null)), - (null, 1, Left(null)), - (1, null, Left(null)), - (true, 12, Right(classOf[CypherTypeException]))) - ) - - val divOperation = Operation("Division", Division.apply, Seq( - (0, 2, Left(0)), - (10, 0, Right(classOf[v3_0.ArithmeticException])), - (-42, 42, Left(-1)), - (1, 2, Left(0)), - (10.0, 0.0, Right(classOf[v3_0.ArithmeticException])), - (-3.25, 13.0, Left(-0.25)), - (0, 2.0, Left(0.0)), - (-9, 3.0, Left(-3.0)), - (null, null, Left(null)), - (1, null, Left(null)), - (null, 1.0, Left(null)), - (true, 2, Right(classOf[CypherTypeException])), - (2.0, true, Right(classOf[CypherTypeException]))) - ) - - val modOperation = Operation("Modulo", Modulo.apply, Seq( - (5, 2, Left(1)), - (3.25, -3, Left(0.25)), - (-14, -5.0, Left(-4.0)), - (null, null, Left(null)), - (42, null, Left(null)), - (null, 42, Left(null)), - (false, 42, Right(classOf[CypherTypeException])), - (5, true, Right(classOf[CypherTypeException]))) - ) - - val operationsToTest = Seq(addOperation, subOperation, mulOperation, divOperation, modOperation) - - for (Operation(name, apply, data) <- operationsToTest) { - - val inputs = data.map { - case (x, y, r) => (asAnyRef(x), asAnyRef(y), asAnyRef(r)) - } - - def project(lhs: CodeGenExpression, rhs: CodeGenExpression) = - Seq(AcceptVisitor("id", Map("result" -> apply(lhs, rhs)))) - inputs.foreach { - case (lhs, rhs, expected) => - - def verify(result: => AnyRef) = expected match { - case Left(x) => - result should equal(List(Map("result" -> x))) - - case Right(x) => - val error = intercept[Exception](result) - withClue(error)(error.getClass should equal(x)) - } - - test(s"$name: literal($lhs) & literal($rhs)") { - verify(evaluate(project(Literal(lhs), Literal(rhs)), columns = Seq("result"), operatorIds = traceIds, - params = Map.empty)) - } - - test(s"$name: parameter($lhs) & parameter($rhs)") { - verify(evaluate(project(Parameter("lhs", "v1"), Parameter("rhs", "v2")), columns = Seq("result"), operatorIds = traceIds, - params = Map("lhs" -> lhs, "rhs" -> rhs))) - } - - test(s"$name: literal($lhs) & parameter($rhs)") { - verify(evaluate(project(Literal(lhs), Parameter("rhs", "v2")), columns = Seq("result"), operatorIds = traceIds, - params = Map("rhs" -> rhs))) - } - - test(s"$name: parameter($lhs) & literal($rhs)") { - verify(evaluate(project(Parameter("lhs", "v2"), Literal(rhs)), columns = Seq("result"), operatorIds = traceIds, - params = Map("lhs" -> lhs))) - } - } - } - - private def asAnyRef(value: Any) = value match { - case x: Int => Int.box(x) - case x: Long => Long.box(x) - case x: Double => Double.box(x) - case x: AnyRef => x - case null => null - } -} diff --git a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/CodeGenSugar.scala b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/CodeGenSugar.scala deleted file mode 100644 index 8f03506e0e343..0000000000000 --- a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/CodeGenSugar.scala +++ /dev/null @@ -1,142 +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.compiler.v3_0.codegen.ir - -import java.time.Clock -import java.util.concurrent.atomic.AtomicInteger - -import org.mockito.Mockito._ -import org.neo4j.cypher.internal.compiler.v3_0.codegen.{Namer, _} -import org.neo4j.cypher.internal.compiler.v3_0.executionplan.ExecutionPlanBuilder.tracer -import org.neo4j.cypher.internal.compiler.v3_0.executionplan._ -import org.neo4j.cypher.internal.compiler.v3_0.planDescription.{Id, InternalPlanDescription} -import org.neo4j.cypher.internal.compiler.v3_0.planner.logical.plans.LogicalPlan -import org.neo4j.cypher.internal.compiler.v3_0.spi.{GraphStatistics, InternalResultRow, InternalResultVisitor, PlanContext, QueryContext} -import org.neo4j.cypher.internal.compiler.v3_0.{CostBasedPlannerName, ExecutionMode, NormalMode, TaskCloser} -import org.neo4j.cypher.internal.frontend.v3_0.SemanticTable -import org.neo4j.cypher.internal.spi.TransactionalContextWrapper -import org.neo4j.cypher.internal.spi.v3_0.TransactionBoundQueryContext.IndexSearchMonitor -import org.neo4j.cypher.internal.spi.v3_0.{GeneratedQueryStructure, TransactionBoundQueryContext} -import org.neo4j.graphdb.GraphDatabaseService -import org.neo4j.kernel.GraphDatabaseQueryService -import org.neo4j.kernel.api.security.AccessMode -import org.neo4j.kernel.api.{KernelTransaction, Statement} -import org.neo4j.kernel.impl.core.ThreadToStatementContextBridge -import org.neo4j.kernel.impl.coreapi.PropertyContainerLocker -import org.neo4j.kernel.impl.query.Neo4jTransactionalContext -import org.scalatest.mock.MockitoSugar - -import scala.collection.JavaConversions - -trait CodeGenSugar extends MockitoSugar { - private val semanticTable = mock[SemanticTable] - - def compile(plan: LogicalPlan) = { - val statistics: GraphStatistics = mock[GraphStatistics] - val context = mock[PlanContext] - doReturn(statistics).when(context).statistics - new CodeGenerator(GeneratedQueryStructure).generate(plan, context, Clock.systemUTC(), semanticTable, CostBasedPlannerName.default) - } - - def compileAndExecute(plan: LogicalPlan, - graphDb: GraphDatabaseQueryService, - mode: ExecutionMode = NormalMode, - params: Map[String, AnyRef] = Map.empty, - taskCloser: TaskCloser = new TaskCloser) = { - executeCompiled(compile(plan), graphDb, mode, params, taskCloser) - } - - def executeCompiled(plan: CompiledPlan, - graphDb: GraphDatabaseQueryService, - mode: ExecutionMode = NormalMode, - params: Map[String, AnyRef] = Map.empty, - taskCloser: TaskCloser = new TaskCloser): InternalExecutionResult = { - val tx = graphDb.beginTransaction(KernelTransaction.Type.explicit, AccessMode.Static.READ) - try { - val statement = graphDb.getDependencyResolver.resolveDependency(classOf[ThreadToStatementContextBridge]).get() - val locker: PropertyContainerLocker = new PropertyContainerLocker - val transactionalContext = new TransactionalContextWrapper(new Neo4jTransactionalContext(graphDb, tx, statement, locker)) - val queryContext = new TransactionBoundQueryContext(transactionalContext)(mock[IndexSearchMonitor]) - val result = plan.executionResultBuilder(queryContext, mode, tracer(mode), params, taskCloser) - tx.success() - result.size - result - } finally { - tx.close() - } - } - - def evaluate(instructions: Seq[Instruction], - qtx: QueryContext = mockQueryContext(), - columns: Seq[String] = Seq.empty, - params: Map[String, AnyRef] = Map.empty, - operatorIds: Map[String, Id] = Map.empty): List[Map[String, Object]] = { - val clazz = compile(instructions, columns, operatorIds) - val result = newInstance(clazz, queryContext = qtx, params = params) - evaluate(result) - } - - def evaluate(result: InternalExecutionResult): List[Map[String, Object]] = { - var rows = List.empty[Map[String, Object]] - val columns: List[String] = result.columns - result.accept(new InternalResultVisitor[RuntimeException] { - override def visit(row: InternalResultRow): Boolean = { - rows = rows :+ columns.map(key => (key, row.get(key))).toMap - true - } - }) - rows - } - - def compile(instructions: Seq[Instruction], columns: Seq[String], operatorIds: Map[String, Id] = Map.empty): GeneratedQuery = { - //In reality the same namer should be used for construction Instruction as in generating code - //these tests separate the concerns so we give this namer non-standard prefixes - CodeGenerator.generateCode(GeneratedQueryStructure)(instructions, operatorIds, columns)( - new CodeGenContext(new SemanticTable(), Map.empty, new Namer( - new AtomicInteger(0), varPrefix = "TEST_VAR", methodPrefix = "TEST_METHOD"))) - } - - def newInstance(clazz: GeneratedQuery, - taskCloser: TaskCloser = new TaskCloser, - queryContext: QueryContext = mockQueryContext(), - graphdb: GraphDatabaseService = null, - executionMode: ExecutionMode = null, - provider: Provider[InternalPlanDescription] = null, - queryExecutionTracer: QueryExecutionTracer = QueryExecutionTracer.NONE, - params: Map[String, AnyRef] = Map.empty): InternalExecutionResult = { - val generated = clazz.execute(taskCloser, queryContext, - executionMode, provider, queryExecutionTracer, JavaConversions.mapAsJavaMap(params)) - new CompiledExecutionResult(taskCloser, queryContext, generated, provider) - } - - def insertStatic(clazz: Class[GeneratedQueryExecution], mappings: (String, Id)*) = mappings.foreach { - case (name, id) => setStaticField(clazz, name, id) - } - - private def mockQueryContext() = { - val qc = mock[QueryContext] - val transactionalContext = mock[TransactionalContextWrapper] - val statement = mock[Statement] - when(qc.transactionalContext).thenReturn(transactionalContext) - when(transactionalContext.statement).thenReturn(statement) - - qc - } -} diff --git a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/CompiledProfilingTest.scala b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/CompiledProfilingTest.scala deleted file mode 100644 index f58effce5192a..0000000000000 --- a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/v3_0/codegen/ir/CompiledProfilingTest.scala +++ /dev/null @@ -1,121 +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.compiler.v3_0.codegen.ir - -import org.mockito.Matchers._ -import org.mockito.Mockito._ -import org.neo4j.collection.primitive.PrimitiveLongIterator -import org.neo4j.cypher.internal.compiler.v3_0.ProfileMode -import org.neo4j.cypher.internal.compiler.v3_0.codegen.Variable -import org.neo4j.cypher.internal.compiler.v3_0.codegen.profiling.ProfilingTracer -import org.neo4j.cypher.internal.compiler.v3_0.executionplan.Provider -import org.neo4j.cypher.internal.compiler.v3_0.planDescription.InternalPlanDescription.Arguments.{DbHits, Rows} -import org.neo4j.cypher.internal.compiler.v3_0.planDescription._ -import org.neo4j.cypher.internal.compiler.v3_0.planner.logical.plans._ -import org.neo4j.cypher.internal.compiler.v3_0.planner.logical.{Cardinality, plans} -import org.neo4j.cypher.internal.compiler.v3_0.planner.{CardinalityEstimation, PlannerQuery} -import org.neo4j.cypher.internal.compiler.v3_0.spi.{QueryContext, QueryTransactionalContext} -import org.neo4j.cypher.internal.frontend.v3_0.ast.SignedDecimalIntegerLiteral -import org.neo4j.cypher.internal.frontend.v3_0.symbols -import org.neo4j.cypher.internal.frontend.v3_0.test_helpers.CypherFunSuite -import org.neo4j.cypher.internal.spi.TransactionalContextWrapper -import org.neo4j.cypher.javacompat.internal.GraphDatabaseCypherService -import org.neo4j.kernel.api._ -import org.neo4j.kernel.api.security.AccessMode -import org.neo4j.kernel.impl.core.{NodeManager, NodeProxy} -import org.neo4j.test.TestGraphDatabaseFactory - -class CompiledProfilingTest extends CypherFunSuite with CodeGenSugar { - - test("should count db hits and rows") { - // given - val id1 = new Id() - val id2 = new Id() - - val variable = Variable("name", symbols.CTNode) - val projectNode = expressions.NodeProjection(variable) - val compiled = compile(Seq(WhileLoop(variable, - ScanAllNodes("OP1"), AcceptVisitor("OP2", Map("n" -> projectNode)))), - Seq("n"), Map("OP1" -> id1, "OP2" -> id2, "X" -> new Id())) - - val readOps = mock[ReadOperations] - val entityAccessor = mock[NodeManager] - val queryContext = mock[QueryContext] - val transactionalContext = mock[TransactionalContextWrapper] - when(queryContext.transactionalContext).thenReturn(transactionalContext.asInstanceOf[QueryTransactionalContext]) - when(transactionalContext.readOperations).thenReturn(readOps) - when(entityAccessor.newNodeProxyById(anyLong())).thenReturn(mock[NodeProxy]) - when(queryContext.entityAccessor).thenReturn(entityAccessor.asInstanceOf[queryContext.EntityAccessor]) - when(readOps.nodesGetAll()).thenReturn(new PrimitiveLongIterator { - private var counter = 0 - - override def next(): Long = counter - - override def hasNext: Boolean = { - counter += 1 - counter < 3 - } - }) - - val provider = new Provider[InternalPlanDescription] { - override def get(): InternalPlanDescription = - PlanDescriptionImpl(id2, "accept", SingleChild(PlanDescriptionImpl(id1, "scanallnodes", NoChildren, Seq.empty, Set.empty)), Seq.empty, Set.empty) - } - - // when - val tracer = new ProfilingTracer() - newInstance(compiled, queryContext = queryContext, provider = provider, queryExecutionTracer = tracer).size - - // then - tracer.dbHitsOf(id1) should equal(3) - tracer.rowsOf(id2) should equal(2) - } - - def single[T](seq: Seq[T]): T = { - seq.size should equal(1) - seq.head - } - - test("should profile hash join") { - //given - val graphDb = new GraphDatabaseCypherService(new TestGraphDatabaseFactory().newImpermanentDatabase()) - val tx = graphDb.beginTransaction(KernelTransaction.Type.explicit, AccessMode.Static.WRITE) - graphDb.createNode() - graphDb.createNode() - tx.success() - tx.close() - - val solved = CardinalityEstimation.lift(PlannerQuery.empty, Cardinality(1)) - val lhs = AllNodesScan(IdName("a"), Set.empty)(solved) - val rhs = AllNodesScan(IdName("a"), Set.empty)(solved) - val join = NodeHashJoin(Set(IdName("a")), lhs, rhs)(solved) - val projection = plans.Projection(join, Map("foo" -> SignedDecimalIntegerLiteral("1")(null)))(solved) - val plan = plans.ProduceResult(List("foo"), projection) - - // when - val result = compileAndExecute(plan, graphDb, mode = ProfileMode) - val description = result.executionPlanDescription() - - // then - val hashJoin = single(description.find("NodeHashJoin")) - hashJoin.arguments should contain(DbHits(0)) - hashJoin.arguments should contain(Rows(2)) - } -} 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 37e9a7040de8c..4910fcd254098 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 @@ -149,7 +149,7 @@ public abstract class GraphDatabaseSettings @Internal public static final Setting cypher_runtime = setting( "unsupported.cypher.runtime", - options( "INTERPRETED", "COMPILED", DEFAULT ), DEFAULT ); + options( "INTERPRETED", DEFAULT ), DEFAULT ); @Description( "Enable tracing of compilation in cypher." ) @Internal diff --git a/community/server/src/test/java/org/neo4j/server/rest/transactional/CypherQueriesIT.java b/community/server/src/test/java/org/neo4j/server/rest/transactional/CypherQueriesIT.java index 1383374b9f3d2..53edee902d53f 100644 --- a/community/server/src/test/java/org/neo4j/server/rest/transactional/CypherQueriesIT.java +++ b/community/server/src/test/java/org/neo4j/server/rest/transactional/CypherQueriesIT.java @@ -33,21 +33,6 @@ public class CypherQueriesIT extends AbstractRestFunctionalTestBase { - @Test - public void runningInCompiledRuntime() throws JsonParseException - { - // Document - ResponseEntity response = gen.get() - .noGraph() - .expectedStatus( 200 ) - .payload( quotedJson( - "{ 'statements': [ { 'statement': 'CYPHER runtime=compiled MATCH (n) RETURN n' } ] }" ) ) - .post( getDataUri() + "transaction/commit" ); - - // Then - Map result = jsonToMap( response.entity() ); - assertNoErrors( result ); - } @Test public void runningWithGeometryTypes() throws JsonParseException diff --git a/community/shell/src/test/java/org/neo4j/shell/TestApps.java b/community/shell/src/test/java/org/neo4j/shell/TestApps.java index b39c2c2d3b9c9..cc3c7c22bd6b5 100644 --- a/community/shell/src/test/java/org/neo4j/shell/TestApps.java +++ b/community/shell/src/test/java/org/neo4j/shell/TestApps.java @@ -1174,7 +1174,6 @@ public void shouldAllowCombiningProfileAndPlanner() throws Exception @Test public void shouldBeAbleToSwitchBetweenRuntimes() throws Exception { - executeCommand( "CYPHER runtime=compiled MATCH (n)-[:T]-(n) RETURN n;" ); executeCommand( "CYPHER runtime=interpreted MATCH (n)-[:T]-(n) RETURN n;" ); }