Skip to content

Commit

Permalink
Expressions as pick tokens in simple CASE form
Browse files Browse the repository at this point in the history
- Resolves #234

Signed-off-by: Dwitry dwitry@users.noreply.github.com
  • Loading branch information
dwitry committed Jan 31, 2019
1 parent 399e6c1 commit ecd3d88
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

import java.util.List;
import java.util.Map;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Test;
import org.opencypher.gremlin.rules.GremlinServerExternalResource;
Expand All @@ -31,6 +32,11 @@ public class CaseTest {
@ClassRule
public static final GremlinServerExternalResource gremlinServer = new GremlinServerExternalResource(TestCommons::modernGraph);

@Before
public void setUp() throws Exception {
TestCommons.modernGraph(gremlinServer.cypherGremlinClient());
}

private List<Map<String, Object>> submitAndGet(String cypher) {
return gremlinServer.cypherGremlinClient().submit(cypher).all();
}
Expand Down Expand Up @@ -230,5 +236,58 @@ public void simpleCaseInWhere() throws Exception {
.containsExactlyInAnyOrder(32L);
}

@Test
public void expressionsInSimpleCase() throws Exception {
List<Map<String, Object>> results = submitAndGet(
"MATCH (n:person) RETURN \n" +
"CASE split(n.name, 'a')[0]\n" +
" WHEN 'm' THEN 1\n" +
" WHEN 'v' THEN 2\n" +
" ELSE NULL\n" +
"END as r"

);

assertThat(results)
.extracting("r")
.containsExactlyInAnyOrder(1L, 2L, null, null);
}

@Test
public void expressionsInSimpleCaseForm() throws Exception {
submitAndGet("CREATE (:test {name: 'a_a'}), (:test {name: 'a_b'}), (:test {name: 'a_c'})");

List<Map<String, Object>> results = submitAndGet(
"MATCH (n:test)\n" +
"RETURN \n" +
" CASE split(n.name, '_')[0] \n" +
" WHEN split(n.name, '_')[1] THEN n.name\n" +
" ELSE NULL\n" +
" END as r\n"
);

assertThat(results)
.extracting("r")
.containsExactlyInAnyOrder("a_a", null, null);
}

@Test
public void expressionsInSimpleCaseFormInWhere() throws Exception {
submitAndGet("CREATE (:test {name: 'a_a'}), (:test {name: 'a_b'}), (:test {name: 'a_c'})");

List<Map<String, Object>> results = submitAndGet(
"MATCH (n)\n" +
"WHERE \n" +
" CASE split(n.name, '_')[0] \n" +
" WHEN split(n.name, '_')[1] THEN n.name\n" +
" ELSE NULL\n" +
" END\n" +
"IS NOT NULL\n" +
"RETURN n.name as r"
);

assertThat(results)
.extracting("r")
.containsExactlyInAnyOrder("a_a");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -603,9 +603,15 @@ private class ExpressionWalker[T, P](context: WalkerContext[T, P], g: GremlinSte
choose.option(Pick.none, defaultValue)
}

val tokensContainsExpressions =
alternatives.map(a => traversalValueOption(a._2, context, context.parameter)).contains(None)

maybeExpr match {
case Some(expr) =>
case Some(expr) if !tokensContainsExpressions =>
optionChoose(expr)
case Some(expr) =>
val name = context.generateName()
__.flatMap(walkLocal(expr)).as(name).flatMap(nestedChoose(__.where(p.isEq(name))))
case None =>
nestedChoose(__.is(p.isEq(true)))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,31 +48,43 @@ object NodeUtils {
value: Any,
context: WalkerContext[T, P],
parameterHandler: String => AnyRef): AnyRef = {

traversalValueOption(value, context, parameterHandler) match {
case Some(javaValue) => javaValue
case None =>
context.unsupported("value expression", value)
}
}

def traversalValueOption[T, P](
value: Any,
context: WalkerContext[T, P],
parameterHandler: String => AnyRef): Option[AnyRef] = {
value match {
case Variable(varName) =>
varName
Some(varName)
case Parameter(name, _) =>
parameterHandler(name)
Some(parameterHandler(name))
case Null() =>
Tokens.NULL
Some(Tokens.NULL)
case ListComprehension(_, Parameter(name, _)) =>
parameterHandler(name)
Some(parameterHandler(name))
case l: Literal =>
l.value
Some(l.value)
case ListLiteral(expressions) =>
traversalValueToJava(expressions, context, parameterHandler)
Some(traversalValueToJava(expressions, context, parameterHandler))
case MapExpression(items) =>
traversalValueToJava(items.toMap, context, parameterHandler)
Some(traversalValueToJava(items.toMap, context, parameterHandler))
case FunctionInvocation(_, _, _, Seq(args)) =>
expressionValue(args, context)
Some(expressionValue(args, context))
case seq: Seq[_] =>
val mappedSeq = seq.map(traversalValueToJava(_, context, parameterHandler))
new util.ArrayList(mappedSeq.asJava)
Some(new util.ArrayList(mappedSeq.asJava))
case map: Map[_, _] =>
val mappedMap = map.mapValues(traversalValueToJava(_, context, parameterHandler))
new util.LinkedHashMap[Any, Any](mappedMap.asJava)
Some(new util.LinkedHashMap[Any, Any](mappedMap.asJava))
case _ =>
context.unsupported("value expression", value)
None
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ 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 @@ -165,7 +164,7 @@ 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)
val value = traversalValueOption(rhs, context, context.parameter).orNull
(value, rhs) match {
case (list: java.lang.Iterable[_], _: ListLiteral) =>
val lhsT = walkExpression(lhs)
Expand Down

0 comments on commit ecd3d88

Please sign in to comment.