Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/3.2' into 3.3
Browse files Browse the repository at this point in the history
  • Loading branch information
systay committed May 9, 2017
2 parents 1ca3fd6 + 6c8c576 commit c4fe909
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ object indexQuery extends GraphElementPropertyFunctions {
throw new InternalException("A CompositeQueryExpression can't be nested in a CompositeQueryExpression")

case RangeQueryExpression(rangeWrapper) =>
throw new InternalException("Range queries on composite indexea not yet supported")
throw new InternalException("Range queries on composite indexes not yet supported")
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
package org.neo4j.cypher.internal.compiler.v3_3.planner.logical.steps

import org.neo4j.cypher.internal.compiler.v3_3.IndexDescriptor
import org.neo4j.cypher.internal.compiler.v3_3.commands.{CompositeQueryExpression, QueryExpression, SingleQueryExpression}
import org.neo4j.cypher.internal.compiler.v3_3.commands.{CompositeQueryExpression, ManyQueryExpression, QueryExpression, SingleQueryExpression}
import org.neo4j.cypher.internal.compiler.v3_3.planner.logical.LeafPlansForVariable.maybeLeafPlans
import org.neo4j.cypher.internal.compiler.v3_3.planner.logical.plans._
import org.neo4j.cypher.internal.compiler.v3_3.planner.logical.{LeafPlanFromExpressions, LeafPlanner, LeafPlansForVariable, LogicalPlanningContext}
Expand Down Expand Up @@ -177,12 +177,22 @@ abstract class AbstractIndexSeekLeafPlanner extends LeafPlanner with LeafPlanFro
}

// Currently we only support using the composite index if ALL properties are specified, but this could be generalized
if (foundPredicates.length == indexDescriptor.properties.length)
if (foundPredicates.length == indexDescriptor.properties.length && isSupportedByCurrentIndexes(foundPredicates))
Some(foundPredicates)
else
None
}

private def isSupportedByCurrentIndexes(foundPredicates: Seq[IndexPlannableExpression]) = {
// We currently only support range queries against single prop indexes
foundPredicates.length == 1 ||
foundPredicates.forall(_.queryExpression match {
case _: SingleQueryExpression[_] => true
case _: ManyQueryExpression[_] => true
case _ => false
})
}

case class IndexPlannableExpression(name: String, propertyKeyName: PropertyKeyName,
propertyPredicate: Expression, queryExpression: QueryExpression[Expression],
hints: Set[Hint], argumentIds: Set[IdName])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,6 @@ import org.neo4j.cypher.{ExecutionEngineFunSuite, NewPlannerTestSupport}

class AggregationAcceptanceTest extends ExecutionEngineFunSuite with NewPlannerTestSupport {

test("apa") {
val r = graph.execute("cypher debug=generate_java_source debug=show_java_source match (n) return n")
while(r.hasNext) r.next()
println(r.getExecutionPlanDescription)
}

// Non-deterministic query -- needs TCK design
test("should aggregate using as grouping key expressions using variables in scope and nothing else") {
val userId = createLabeledNode(Map("userId" -> 11), "User")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ class CompositeIndexAcceptanceTest extends ExecutionEngineFunSuite with NewPlann
graph should haveIndexes(":L(foo,bar,baz)")
val result = executeWithAllPlanners("MATCH (n:L {foo: 42, bar: 1337, baz: 1980}) RETURN count(n)")
result should evaluateTo(Seq(Map("count(n)" -> 1)))
result should useIndex(":L(foo,bar,baz")
result should useIndex(":L(foo,bar,baz)")
}

test("should not fail on multiple attempts to create a composite index") {
Expand All @@ -280,6 +280,31 @@ class CompositeIndexAcceptanceTest extends ExecutionEngineFunSuite with NewPlann
executeWithCostPlannerAndInterpretedRuntimeOnly("CREATE INDEX ON :Person(firstname, lastname)")
}

test("should not use range queries against a composite index") {
// given
graph.createIndex("X", "p1", "p2")
val n = createLabeledNode(Map("p1" -> 1, "p2" -> 1), "X")
val result = executeWithAllPlanners("match (n:X) where n.p1 = 1 AND n.p2 > 0 return n;")

result should evaluateTo(Seq(Map("n" -> n)))
result shouldNot useIndex(":X(p1,p2)")
}

test("nested index join with composite indexes") {
// given
graph.createIndex("X", "p1", "p2")
(1 to 1000) foreach { _ => // Get the planner to do what we expect it to!
createLabeledNode("X")
}
val a = createNode("p1" -> 1, "p2" -> 1)
val b = createLabeledNode(Map("p1" -> 1, "p2" -> 1), "X")
val result = executeWithAllPlanners("match (a), (b:X) where id(a) = $id AND b.p1 = a.p1 AND b.p2 = 1 return b",
"id" -> a.getId)

result should evaluateTo(Seq(Map("b" -> b)))
result should useIndex(":X(p1,p2)")
}

case class haveIndexes(expectedIndexes: String*) extends Matcher[GraphDatabaseQueryService] {
def apply(graph: GraphDatabaseQueryService): MatchResult = {
graph.inTx {
Expand Down

0 comments on commit c4fe909

Please sign in to comment.