Skip to content

Commit

Permalink
Merge branch 'master' into grave_liskov
Browse files Browse the repository at this point in the history
  • Loading branch information
dwitry committed Jan 18, 2019
2 parents cc4df26 + 890ad64 commit 9062df8
Show file tree
Hide file tree
Showing 4 changed files with 189 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -197,4 +197,55 @@ public void constantsInequality() {
.containsExactlyInAnyOrder("lop", "ripple");
}

@Test
public void inInteger() {
List<Map<String, Object>> results = submitAndGet(
"MATCH (n:person) " +
"WHERE n.age IN [29, 27] " +
"RETURN n.name"
);

assertThat(results)
.extracting("n.name")
.containsExactlyInAnyOrder("marko", "vadas");
}

@Test
public void inString() {
List<Map<String, Object>> results = submitAndGet(
"MATCH (n:person) " +
"WHERE n.name IN ['marko', 'vadas'] " +
"RETURN n.age"
);

assertThat(results)
.extracting("n.age")
.containsExactlyInAnyOrder(29L, 27L);
}

@Test
public void inSingle() {
List<Map<String, Object>> results = submitAndGet(
"MATCH (n:person) " +
"WHERE n.age IN [27] " +
"RETURN n.name"
);

assertThat(results)
.extracting("n.name")
.containsExactlyInAnyOrder("vadas");
}

@Test
public void notIn() {
List<Map<String, Object>> results = submitAndGet(
"MATCH (n:person) " +
"WHERE NOT n.name IN ['marko', 'vadas'] " +
"RETURN n.name"
);

assertThat(results)
.extracting("n.name")
.containsExactlyInAnyOrder("josh", "peter");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@
*/
package org.opencypher.gremlin.translation.ir.rewrite

import org.apache.tinkerpop.gremlin.structure.T
import org.opencypher.gremlin.translation.ir.TraversalHelper._
import org.opencypher.gremlin.translation.ir.model._
import org.opencypher.gremlin.translation.ir.model.{Id, _}

import scala.collection.mutable

Expand Down Expand Up @@ -93,6 +94,11 @@ object GroupStepFilters extends GremlinRewriter {
traversals.flatMap {
case SelectK(stepLabel) :: Values(propertyKey) :: Is(predicate) :: Nil =>
(stepLabel, HasP(propertyKey, predicate)) :: Nil
case SelectK(stepLabel) :: ChooseP2(_, Id :: Nil) :: Is(_) :: Is(predicate) :: Nil =>
(stepLabel, HasP(T.id.getAccessor, predicate)) :: Nil
case ChooseT3(Seq(Constant(value)), _, _) :: Is(_) :: As(_) :: SelectK(stepLabel) :: ChooseP2(_, Seq(Id)) :: Is(_) :: WhereP(
_: Eq) :: Nil =>
(stepLabel, HasP(T.id.getAccessor, Eq(value))) :: Nil
case SelectK(stepLabel) :: rest if rest.forall(_.isInstanceOf[HasLabel]) =>
rest.map((stepLabel, _))
case _ =>
Expand All @@ -105,6 +111,11 @@ object GroupStepFilters extends GremlinRewriter {
val newTraversals = traversals.flatMap {
case SelectK(alias) :: Values(_) :: Is(_) :: Nil if aliases.contains(alias) =>
None
case SelectK(alias) :: ChooseP2(_, Id :: Nil) :: Is(_) :: Is(_) :: Nil if aliases.contains(alias) =>
None
case ChooseT3(Seq(Constant(_)), _, _) :: Is(_) :: As(_) :: SelectK(alias) :: ChooseP2(_, Seq(Id)) :: Is(_) :: WhereP(
_: Eq) :: Nil if aliases.contains(alias) =>
None
case SelectK(alias) :: rest if aliases.contains(alias) && rest.forall(_.isInstanceOf[HasLabel]) =>
None
case other =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ import org.opencypher.v9_0.expressions._
import org.opencypher.v9_0.util.InputPosition
import org.opencypher.v9_0.util.symbols._

import scala.collection.JavaConverters._
import scala.collection.mutable
import scala.util.Try

/**
* AST walker that handles translation
Expand Down Expand Up @@ -142,8 +144,8 @@ private class WhereWalker[T, P](context: WalkerContext[T, P], g: GremlinSteps[T,
case StartsWith(lhs, rhs) => walkPredicate(lhs, rhs, p.startsWith)
case EndsWith(lhs, rhs) => walkPredicate(lhs, rhs, p.endsWith)
case Contains(lhs, rhs) => walkPredicate(lhs, rhs, p.contains)
case In(lhs, rhs) => walkPredicate(lhs, rhs, p.within(_))
case Not(In(lhs, rhs)) => walkPredicate(lhs, rhs, p.without(_))
case In(lhs, rhs) => walkVargPredicate(lhs, rhs, a => p.within(a: _*))
case Not(In(lhs, rhs)) => walkVargPredicate(lhs, rhs, a => p.without(a: _*))

case Ands(ands) => __.and(ands.map(walkBooleanExpression).toSeq: _*)
case Ors(ors) => __.or(ors.map(walkBooleanExpression).toSeq: _*)
Expand All @@ -162,6 +164,18 @@ private class WhereWalker[T, P](context: WalkerContext[T, P], g: GremlinSteps[T,
}
}

private def walkVargPredicate(lhs: Expression, rhs: Expression, predicate: Seq[AnyRef] => P): GremlinSteps[T, P] = {
val value = Try(expressionValue(rhs, context)).getOrElse(null)
(value, rhs) match {
case (list: java.lang.Iterable[_], _: ListLiteral) =>
val lhsT = walkExpression(lhs)
val seq = list.asScala.map(_.asInstanceOf[AnyRef]).toSeq
lhsT.is(predicate(seq))
case _ =>
walkPredicate(lhs, rhs, a => predicate(Seq(a)))
}
}

private def walkPredicate(lhs: Expression, rhs: Expression, predicate: AnyRef => P): GremlinSteps[T, P] = {
val lhsT = walkExpression(lhs)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,19 @@
*/
package org.opencypher.gremlin.translation.ir.rewrite

import org.apache.tinkerpop.gremlin.structure.T
import org.apache.tinkerpop.gremlin.structure.VertexProperty.Cardinality.single
import org.junit.Test
import org.opencypher.gremlin.translation.CypherAst.parse
import org.opencypher.gremlin.translation.Tokens.UNNAMED
import org.opencypher.gremlin.translation.Tokens
import org.opencypher.gremlin.translation.Tokens.{GENERATED, NULL, UNNAMED}
import org.opencypher.gremlin.translation.ir.helpers.CypherAstAssert.{P, __}
import org.opencypher.gremlin.translation.ir.helpers.CypherAstAssertions.assertThat
import org.opencypher.gremlin.translation.ir.model.GremlinBinding
import org.opencypher.gremlin.translation.translator.TranslatorFlavor

import scala.collection.JavaConversions._

class GroupStepFiltersTest {

val flavor = new TranslatorFlavor(
Expand Down Expand Up @@ -78,6 +83,110 @@ class GroupStepFiltersTest {
)
}

@Test
def whereId(): Unit = {
assertThat(parse("""
|MATCH (n)
|WHERE id(n) = 1
|RETURN n
""".stripMargin))
.withFlavor(flavor)
.rewritingWith(GroupStepFilters)
.removes(
__.where(__.select("n").choose(P.neq(Tokens.NULL), __.id()).is(P.neq(Tokens.NULL)).is(P.isEq(1)))
)
.adds(
__.has(T.id.getAccessor, P.isEq(1))
)
}

@Test
def whereIdIn(): Unit = {
assertThat(parse("""
|MATCH (n)
|WHERE id(n) in [1]
|RETURN n
""".stripMargin))
.withFlavor(flavor)
.rewritingWith(GroupStepFilters)
.removes(
__.where(
__.select("n")
.choose(P.neq(NULL), __.id())
.is(P.neq(NULL))
.is(P.within(1.asInstanceOf[AnyRef])))
)
.adds(__.has(T.id.getAccessor, P.within(1.asInstanceOf[AnyRef])))
}

@Test
def whereIdInMultiple(): Unit = {
assertThat(parse("""
|MATCH (n)
|WHERE id(n) in [1, 2]
|RETURN n
""".stripMargin))
.withFlavor(flavor)
.rewritingWith(GroupStepFilters)
.removes(
__.where(
__.select("n")
.choose(P.neq(NULL), __.id())
.is(P.neq(NULL))
.is(P.within(1.asInstanceOf[AnyRef], 2.asInstanceOf[AnyRef]))
))
.adds(__.has(T.id.getAccessor, P.within(1.asInstanceOf[AnyRef], 2.asInstanceOf[AnyRef])))
}

@Test
def whereWithParam(): Unit = {
val params = new java.util.HashMap[String, Any](Map("nID" -> 1))
assertThat(
parse(
"""
|MATCH (n)
|WHERE id(n) = {nID}
|RETURN n
""".stripMargin,
params
))
.withFlavor(flavor)
.rewritingWith(GroupStepFilters)
.removes(
__.where(
__.choose(__.constant(GremlinBinding("nID")), __.constant(GremlinBinding("nID")), __.constant(NULL))
.is(P.neq(NULL))
.as(GENERATED + 1)
.select("n")
.choose(P.neq(NULL), __.id())
.is(P.neq(NULL))
.where(P.isEq(GENERATED + 1))))
.adds(__.has(T.id.getAccessor, P.isEq(GremlinBinding("nID"))))
}

@Test
def whereWithParams(): Unit = {
val params = new java.util.HashMap[String, Any](Map("nID" -> 1))
assertThat(
parse(
"""
|MATCH (n)
|WHERE id(n) IN [{nID}]
|RETURN n
""".stripMargin,
params
))
.withFlavor(flavor)
.rewritingWith(GroupStepFilters)
.removes(
__.where(
__.select("n")
.choose(P.neq(NULL), __.id())
.is(P.neq(NULL))
.is(P.within(GremlinBinding("nID"))))
)
.adds(__.has(T.id.getAccessor, P.within(GremlinBinding("nID"))))
}
@Test
def multiplePatterns(): Unit = {
assertThat(parse("""
Expand Down

0 comments on commit 9062df8

Please sign in to comment.