Skip to content

Commit

Permalink
Merge 2.3 into 3.0
Browse files Browse the repository at this point in the history
  • Loading branch information
davidegrohmann committed Jan 15, 2016
2 parents a866b9f + 49dbda7 commit 0c07b89
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,16 @@ class WithAcceptanceTest extends ExecutionEngineFunSuite with NewPlannerTestSupp
result.toSet should equal(Set(Map("nestedMap.foo.bar" -> "baz")))
}

test("connected components after WITH") {
val n = createLabeledNode("A")
val m = createLabeledNode("B")
val x = createNode()
relate(n, x)

val result = executeWithAllPlanners("MATCH (n:A) WITH n LIMIT 1 MATCH (m:B), (n)-->(x) RETURN *")

result.toList should equal(List(Map("m" -> m, "n" -> n, "x" -> x)))
}

test("WITH with predicate and aggregation should be handled by all planners") {
// GIVEN
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -203,14 +203,10 @@ case class QueryGraph(patternRelationships: Set[PatternRelationship] = Set.empty

private def connectedComponentFor(startNode: IdName, visited: mutable.Set[IdName]): QueryGraph = {
val queue = mutable.Queue(startNode)
val nodesSolvedByArguments = patternNodes intersect argumentIds
queue.enqueue(nodesSolvedByArguments.toSeq:_*)
var qg = QueryGraph.empty.withArgumentIds(argumentIds)
var qg = QueryGraph.empty
while (queue.nonEmpty) {
val node = queue.dequeue()
qg = if (visited(node)) {
qg
} else {
if (!visited(node)) {
visited += node

val filteredPatterns = patternRelationships.filter { rel =>
Expand All @@ -219,14 +215,31 @@ case class QueryGraph(patternRelationships: Set[PatternRelationship] = Set.empty

queue.enqueue(filteredPatterns.toSeq.map(_.otherSide(node)): _*)

qg
qg = qg
.addPatternNodes(node)
.addPatternRelationships(filteredPatterns.toSeq)

val alreadyHaveArguments = qg.argumentIds.nonEmpty

if (!alreadyHaveArguments && (relationshipPullsInArguments(qg.coveredIds) || predicatePullsInArguments(node))) {
qg = qg.withArgumentIds(argumentIds)
val nodesSolvedByArguments = patternNodes intersect qg.argumentIds
queue.enqueue(nodesSolvedByArguments.toSeq: _*)
}
}
}
qg
}

private def relationshipPullsInArguments(coveredIds: Set[IdName]) = (argumentIds intersect coveredIds).nonEmpty

private def predicatePullsInArguments(node: IdName) = selections.flatPredicates.exists {
case p =>
val deps = p.dependencies.map(IdName.fromVariable)
deps(node) && (deps intersect argumentIds).nonEmpty
}


// This is here to stop usage of copy from the outside
private def copy(patternRelationships: Set[PatternRelationship] = patternRelationships,
patternNodes: Set[IdName] = patternNodes,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,10 @@ class QueryGraphConnectedComponentsTest
private val B = IdName("b")
private val C = IdName("c")
private val X = IdName("x")
private val R1 = PatternRelationship(IdName("r1"), (A, B), SemanticDirection.OUTGOING, Seq.empty, SimplePatternLength)
private val R2 = PatternRelationship(IdName("r3"), (B, A), SemanticDirection.OUTGOING, Seq.empty, SimplePatternLength)
private val R3 = PatternRelationship(IdName("r7"), (C, X), SemanticDirection.OUTGOING, Seq.empty, SimplePatternLength)
private val A_to_B = PatternRelationship(IdName("r1"), (A, B), SemanticDirection.OUTGOING, Seq.empty, SimplePatternLength)
private val B_to_A = PatternRelationship(IdName("r3"), (B, A), SemanticDirection.OUTGOING, Seq.empty, SimplePatternLength)
private val C_to_X = PatternRelationship(IdName("r7"), (C, X), SemanticDirection.OUTGOING, Seq.empty, SimplePatternLength)
private val B_to_X = PatternRelationship(IdName("r12"), (B, X), SemanticDirection.OUTGOING, Seq.empty, SimplePatternLength)
private val identA = varFor(A.name)
private val identB = varFor(B.name)

Expand All @@ -61,7 +62,7 @@ class QueryGraphConnectedComponentsTest
test("two nodes connected through one rel") {
val graph = QueryGraph(
patternNodes = Set(A, B),
patternRelationships = Set(R1)
patternRelationships = Set(A_to_B)
)

graph.connectedComponents should equal(Seq(graph))
Expand All @@ -70,32 +71,32 @@ class QueryGraphConnectedComponentsTest
test("two disconnected relationships") {
val graph = QueryGraph(
patternNodes = Set(A, B, C, X),
patternRelationships = Set(R1, R3)
patternRelationships = Set(A_to_B, C_to_X)
)

graph.connectedComponents should equal(Seq(
QueryGraph(patternNodes = Set(A, B), patternRelationships = Set(R1)),
QueryGraph(patternNodes = Set(C, X), patternRelationships = Set(R3))
QueryGraph(patternNodes = Set(A, B), patternRelationships = Set(A_to_B)),
QueryGraph(patternNodes = Set(C, X), patternRelationships = Set(C_to_X))
))
}

test("two disconnected relationships with one argument") {
val graph = QueryGraph(
patternNodes = Set(A, B, C, X),
patternRelationships = Set(R1, R3),
patternRelationships = Set(A_to_B, C_to_X),
argumentIds = Set(A)
)

graph.connectedComponents should equal(Seq(
QueryGraph(patternNodes = Set(A, B), patternRelationships = Set(R1), argumentIds = Set(A)),
QueryGraph(patternNodes = Set(C, X), patternRelationships = Set(R3), argumentIds = Set(A))
QueryGraph(patternNodes = Set(A, B), patternRelationships = Set(A_to_B), argumentIds = Set(A)),
QueryGraph(patternNodes = Set(C, X), patternRelationships = Set(C_to_X), argumentIds = Set(A))
))
}

test("two disconnected relationships with each one argument") {
val graph = QueryGraph(
patternNodes = Set(A, B, C, X),
patternRelationships = Set(R1, R3),
patternRelationships = Set(A_to_B, C_to_X),
argumentIds = Set(A, C)
)

Expand All @@ -106,7 +107,7 @@ class QueryGraphConnectedComponentsTest
val graph = QueryGraph(
patternNodes = Set(A, B),
optionalMatches = Seq(
QueryGraph(patternNodes = Set(A, B), argumentIds = Set(A, B), patternRelationships = Set(R1))
QueryGraph(patternNodes = Set(A, B), argumentIds = Set(A, B), patternRelationships = Set(A_to_B))
)
)

Expand Down Expand Up @@ -144,18 +145,18 @@ class QueryGraphConnectedComponentsTest
}

test("two disconnected relationships with each predicate on one of the relationships") {
val propA = Property(varFor(R1.name.name), propKeyName)(pos)
val propA = Property(varFor(A_to_B.name.name), propKeyName)(pos)
val predicate = Equals(propA, StringLiteral("something")(pos))(pos)

val graph = QueryGraph(
patternNodes = Set(A, B, C, X),
patternRelationships = Set(R1, R3),
patternRelationships = Set(A_to_B, C_to_X),
selections = Selections.from(predicate)
)

graph.connectedComponents should equal(Seq(
QueryGraph(patternNodes = Set(A, B), patternRelationships = Set(R1), selections = Selections.from(predicate)),
QueryGraph(patternNodes = Set(C, X), patternRelationships = Set(R3))
QueryGraph(patternNodes = Set(A, B), patternRelationships = Set(A_to_B), selections = Selections.from(predicate)),
QueryGraph(patternNodes = Set(C, X), patternRelationships = Set(C_to_X))
))
}

Expand All @@ -169,7 +170,7 @@ class QueryGraphConnectedComponentsTest
}

test("two disconnected pattern nodes with one shortest path between them") {
val shortestPath: ShortestPathPattern = ShortestPathPattern(Some(IdName("r")), R1, single = true)(null)
val shortestPath: ShortestPathPattern = ShortestPathPattern(Some(IdName("r")), A_to_B, single = true)(null)

val graph = QueryGraph(patternNodes = Set(A, B), shortestPathPatterns = Set(shortestPath))

Expand All @@ -180,11 +181,11 @@ class QueryGraphConnectedComponentsTest
}

test("a connected pattern that has a shortest path in it") {
val shortestPath: ShortestPathPattern = ShortestPathPattern(Some(IdName("r")), R1, single = true)(null)
val shortestPath: ShortestPathPattern = ShortestPathPattern(Some(IdName("r")), A_to_B, single = true)(null)

val graph = QueryGraph(
patternNodes = Set(A, B),
patternRelationships = Set(R2),
patternRelationships = Set(B_to_A),
shortestPathPatterns = Set(shortestPath))

graph.connectedComponents should equal(Seq(graph))
Expand Down Expand Up @@ -214,4 +215,22 @@ class QueryGraphConnectedComponentsTest

graph.connectedComponents should equal(Seq(graph))
}

test("one node and a relationship connected through an optional QG") {
// MATCH (a), (b)-->(x)
val graph = QueryGraph(
argumentIds = Set(X),
patternNodes = Set(A, B, X),
patternRelationships = Set(B_to_X),
optionalMatches = Seq(
QueryGraph(patternNodes = Set(A, B), argumentIds = Set(A, B), patternRelationships = Set(A_to_B))
)
)

val components = graph.connectedComponents
components should equal(Seq(
QueryGraph(patternNodes = Set(A), argumentIds = Set(X)),
QueryGraph(patternNodes = Set(B, X), patternRelationships = Set(B_to_X), argumentIds = Set(X))
))
}
}

0 comments on commit 0c07b89

Please sign in to comment.