Skip to content

Commit

Permalink
Use cardinality = single for Vertex properties
Browse files Browse the repository at this point in the history
Signed-off-by: Dwitry [email protected]
  • Loading branch information
dwitry committed Jul 3, 2018
1 parent addea3f commit 83cb6ff
Show file tree
Hide file tree
Showing 17 changed files with 266 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import org.apache.tinkerpop.gremlin.process.traversal.Order;
import org.apache.tinkerpop.gremlin.process.traversal.Scope;
import org.apache.tinkerpop.gremlin.structure.Column;
import org.apache.tinkerpop.gremlin.structure.VertexProperty.Cardinality;
import org.opencypher.gremlin.translation.translator.Translator;
import org.opencypher.gremlin.traversal.CustomFunction;

Expand Down Expand Up @@ -173,8 +174,12 @@ GremlinSteps<T, P> choose(GremlinSteps<T, P> traversalPredicate,

GremlinSteps<T, P> property(String key, Object value);

GremlinSteps<T, P> property(Cardinality cardinality, String key, Object value);

GremlinSteps<T, P> property(String key, GremlinSteps<T, P> traversal);

GremlinSteps<T, P> property(Cardinality cardinality, String key, GremlinSteps<T, P> traversal);

GremlinSteps<T, P> project(String... keys);

GremlinSteps<T, P> range(Scope scope, long low, long high);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.apache.tinkerpop.gremlin.process.traversal.Scope;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal.Symbols;
import org.apache.tinkerpop.gremlin.structure.Column;
import org.apache.tinkerpop.gremlin.structure.VertexProperty.Cardinality;
import org.apache.tinkerpop.gremlin.util.function.Lambda;
import org.opencypher.gremlin.translation.GremlinSteps;
import org.opencypher.gremlin.traversal.CustomFunction;
Expand Down Expand Up @@ -408,12 +409,24 @@ public GremlinSteps<Bytecode, P> property(String key, Object value) {
return this;
}

@Override
public GremlinSteps<Bytecode, P> property(Cardinality cardinality, String key, Object value) {
bytecode.addStep(Symbols.property, cardinality, key, value);
return this;
}

@Override
public GremlinSteps<Bytecode, P> property(String key, GremlinSteps<Bytecode, P> traversal) {
bytecode.addStep(Symbols.property, key, traversal.current());
return this;
}

@Override
public GremlinSteps<Bytecode, P> property(Cardinality cardinality, String key, GremlinSteps<Bytecode, P> traversal) {
bytecode.addStep(Symbols.property, cardinality, key, traversal.current());
return this;
}

@Override
public GremlinSteps<Bytecode, P> project(String... keys) {
bytecode.addStep(Symbols.project, (Object[]) keys);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import org.apache.tinkerpop.gremlin.process.traversal.Order;
import org.apache.tinkerpop.gremlin.process.traversal.Scope;
import org.apache.tinkerpop.gremlin.structure.Column;
import org.apache.tinkerpop.gremlin.structure.VertexProperty.Cardinality;
import org.opencypher.gremlin.translation.GremlinSteps;
import org.opencypher.gremlin.traversal.CustomFunction;

Expand Down Expand Up @@ -418,12 +419,24 @@ public GremlinSteps<String, GroovyPredicate> property(String key, Object value)
return this;
}

@Override
public GremlinSteps<String, GroovyPredicate> property(Cardinality cardinality, String key, Object value) {
g.append(chain("property", cardinality, key, value));
return this;
}

@Override
public GremlinSteps<String, GroovyPredicate> property(String key, GremlinSteps<String, GroovyPredicate> traversal) {
g.append(chain("property", key, traversal(traversal)));
return this;
}

@Override
public GremlinSteps<String, GroovyPredicate> property(Cardinality cardinality, String key, GremlinSteps<String, GroovyPredicate> traversal) {
g.append(chain("property", cardinality, key, traversal(traversal)));
return this;
}

@Override
public GremlinSteps<String, GroovyPredicate> project(String... keys) {
g.append(chain("project", (Object[]) keys));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import org.apache.tinkerpop.gremlin.structure.Column;
import org.apache.tinkerpop.gremlin.structure.Edge;
import org.apache.tinkerpop.gremlin.structure.Vertex;
import org.apache.tinkerpop.gremlin.structure.VertexProperty.Cardinality;
import org.apache.tinkerpop.gremlin.structure.util.empty.EmptyGraph;
import org.opencypher.gremlin.translation.GremlinSteps;
import org.opencypher.gremlin.traversal.CustomFunction;
Expand Down Expand Up @@ -445,11 +446,23 @@ public GremlinSteps<GraphTraversal, P> property(String key, Object value) {
return this;
}

@Override
public GremlinSteps<GraphTraversal, P> property(Cardinality cardinality, String key, Object value) {
g.property(cardinality, key, value);
return this;
}

@Override
public GremlinSteps<GraphTraversal, P> property(String key, GremlinSteps<GraphTraversal, P> traversal) {
return property(key, traversal.current());
}

@Override
public GremlinSteps<GraphTraversal, P> property(Cardinality cardinality, String key, GremlinSteps<GraphTraversal, P> traversal) {
g.property(cardinality, key, traversal.current());
return this;
}

@Override
public GremlinSteps<GraphTraversal, P> project(String... keys) {
if (keys.length >= 1) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,8 +181,12 @@ sealed class TranslationWriter[T, P] private (translator: Translator[T, P], para
g.properties(propertyKeys: _*)
case PropertyV(key, value) =>
g.property(key, writeValue(value))
case PropertyVC(cardinality, key, value) =>
g.property(cardinality, key, writeValue(value))
case PropertyT(key, traversal) =>
g.property(key, writeLocalSteps(traversal))
case PropertyTC(cardinality, key, traversal) =>
g.property(cardinality, key, writeLocalSteps(traversal))
case Project(keys @ _*) =>
g.project(keys: _*)
case Range(scope: Scope, low: Long, high: Long) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package org.opencypher.gremlin.translation.ir.builder

import org.apache.tinkerpop.gremlin.process.traversal.{Scope, Order => TOrder}
import org.apache.tinkerpop.gremlin.structure.Column
import org.apache.tinkerpop.gremlin.structure.VertexProperty.Cardinality
import org.opencypher.gremlin.translation.GremlinSteps
import org.opencypher.gremlin.translation.ir.model._
import org.opencypher.gremlin.traversal.CustomFunction
Expand Down Expand Up @@ -348,13 +349,29 @@ class IRGremlinSteps extends GremlinSteps[Seq[GremlinStep], GremlinPredicate] {
this
}

override def property(
cardinality: Cardinality,
key: String,
value: Any): GremlinSteps[Seq[GremlinStep], GremlinPredicate] = {
buf += PropertyVC(cardinality, key, value)
this
}

override def property(
key: String,
traversal: GremlinSteps[Seq[GremlinStep], GremlinPredicate]): GremlinSteps[Seq[GremlinStep], GremlinPredicate] = {
buf += PropertyT(key, traversal.current())
this
}

override def property(
cardinality: Cardinality,
key: String,
traversal: GremlinSteps[Seq[GremlinStep], GremlinPredicate]): GremlinSteps[Seq[GremlinStep], GremlinPredicate] = {
buf += PropertyTC(cardinality, key, traversal.current())
this
}

override def project(keys: String*): GremlinSteps[Seq[GremlinStep], GremlinPredicate] = {
buf += Project(keys: _*)
this
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package org.opencypher.gremlin.translation.ir.model

import org.apache.tinkerpop.gremlin.process.traversal.{Scope, Order => TraversalOrder}
import org.apache.tinkerpop.gremlin.structure.Column
import org.apache.tinkerpop.gremlin.structure.VertexProperty.Cardinality
import org.opencypher.gremlin.traversal.CustomFunction

sealed trait GremlinStep {
Expand Down Expand Up @@ -247,6 +248,8 @@ case class Properties(propertyKeys: String*) extends GremlinStep

case class PropertyV(key: String, value: Any) extends GremlinStep

case class PropertyVC(cardinality: Cardinality, key: String, value: Any) extends GremlinStep

case class PropertyT(key: String, traversal: Seq[GremlinStep]) extends GremlinStep {
override def mapTraversals(f: Seq[GremlinStep] => Seq[GremlinStep]): GremlinStep = {
PropertyT(key, f(traversal))
Expand All @@ -257,6 +260,16 @@ case class PropertyT(key: String, traversal: Seq[GremlinStep]) extends GremlinSt
}
}

case class PropertyTC(cardinality: Cardinality, key: String, traversal: Seq[GremlinStep]) extends GremlinStep {
override def mapTraversals(f: Seq[GremlinStep] => Seq[GremlinStep]): GremlinStep = {
PropertyTC(cardinality, key, f(traversal))
}

override def foldTraversals[R](z: R)(op: (R, Seq[GremlinStep]) => R): R = {
op(z, traversal)
}
}

case class Project(keys: String*) extends GremlinStep

case class Range(scope: Scope, low: Long, high: Long) extends GremlinStep
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ object NeptuneFlavor extends GremlinRewriter {

private def expandListProperties(steps: Seq[GremlinStep]): Seq[GremlinStep] = {
replace({
case PropertyT(key, Project(_*) :: bySteps) :: rest => {
case PropertyTC(_, key, Project(_*) :: bySteps) :: rest => {
expandSub(key, bySteps) ++ rest
}
})(steps)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ object SimplifyPropertySetters extends GremlinRewriter {
mapTraversals(replace({
case PropertyT(key, Constant(value) :: Nil) :: rest =>
PropertyV(key, value) :: rest
case PropertyTC(cardinality, key, Constant(value) :: Nil) :: rest =>
PropertyVC(cardinality, key, value) :: rest
case ChooseT(_, PropertyV(key, value) :: Nil, drop) :: rest =>
val empty = value match {
case NULL => true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,17 @@
*/
package org.opencypher.gremlin.translation.walker

import org.apache.tinkerpop.gremlin.structure.VertexProperty.Cardinality
import org.apache.tinkerpop.gremlin.structure.VertexProperty.Cardinality.single
import org.opencypher.gremlin.translation.GremlinSteps
import org.opencypher.gremlin.translation.context.WalkerContext
import org.opencypher.gremlin.translation.exception.SyntaxException
import org.opencypher.gremlin.translation.walker.NodeUtils.setProperty
import org.opencypher.v9_0.ast._
import org.opencypher.v9_0.expressions.SemanticDirection.INCOMING
import org.opencypher.v9_0.expressions._
import org.opencypher.v9_0.util.ASTNode
import org.opencypher.v9_0.util.symbols.{CypherType, NodeType, RelationshipType}

import scala.collection.mutable

Expand Down Expand Up @@ -84,7 +88,7 @@ private class CreateWalker[T, P](context: WalkerContext[T, P], g: GremlinSteps[T
}

val properties = getPropertiesMap(propertiesOption)
walkProperties(properties)
walkProperties(NodeType.instance, properties)
case _ =>
context.unsupported("node pattern", nodePattern)
}
Expand All @@ -111,21 +115,21 @@ private class CreateWalker[T, P](context: WalkerContext[T, P], g: GremlinSteps[T
}
g.as(rName)

walkProperties(properties)
walkProperties(RelationshipType.instance, properties)
}
case _ =>
context.unsupported("relationship pattern", relationshipPattern)
}
}

def walkProperties(properties: Seq[(String, Expression)]): Unit = {
def walkProperties(cypherType: CypherType, properties: Seq[(String, Expression)]): Unit = {
properties.filter {
case (_, Null()) => false
case _ => true
}.foreach {
case (key, expression) =>
val traversal = ExpressionWalker.walkLocal(context, g, expression)
g.property(key, traversal)
setProperty(g, cypherType, key, traversal)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package org.opencypher.gremlin.translation.walker

import org.apache.tinkerpop.gremlin.process.traversal.Scope
import org.apache.tinkerpop.gremlin.structure.VertexProperty.Cardinality.single
import org.apache.tinkerpop.gremlin.structure.{Column, Vertex}
import org.opencypher.gremlin.translation.GremlinSteps
import org.opencypher.gremlin.translation.Tokens._
Expand Down Expand Up @@ -46,9 +47,10 @@ object ExpressionWalker {
def walkProperty[T, P](
context: WalkerContext[T, P],
g: GremlinSteps[T, P],
cypherType: CypherType,
key: String,
value: Expression): GremlinSteps[T, P] = {
new ExpressionWalker(context, g).walkProperty(key, value)
new ExpressionWalker(context, g).walkProperty(cypherType, key, value)
}
}

Expand Down Expand Up @@ -281,12 +283,12 @@ private class ExpressionWalker[T, P](context: WalkerContext[T, P], g: GremlinSte
}
}

def walkProperty(key: String, value: Expression): GremlinSteps[T, P] = {
def walkProperty(cypherType: CypherType, key: String, value: Expression): GremlinSteps[T, P] = {
val p = context.dsl.predicates()
val traversal = walkLocal(value)
g.choose(
g.start().flatMap(traversal).is(p.neq(NULL)).unfold(),
g.start().property(key, traversal),
setProperty(g.start(), cypherType, key, traversal),
g.start().sideEffect(g.start().properties(key).drop())
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,13 @@ package org.opencypher.gremlin.translation.walker
import java.util

import org.apache.tinkerpop.gremlin.structure.Column
import org.apache.tinkerpop.gremlin.structure.VertexProperty.Cardinality.single
import org.opencypher.gremlin.translation.Tokens._
import org.opencypher.gremlin.translation.context.WalkerContext
import org.opencypher.gremlin.translation.{GremlinSteps, Tokens}
import org.opencypher.v9_0.expressions._
import org.opencypher.v9_0.util.ASTNode
import org.opencypher.v9_0.util.symbols.{CypherType, NodeType, RelationshipType}

import scala.collection.JavaConverters._

Expand Down Expand Up @@ -158,4 +160,16 @@ object NodeUtils {
.map(alias => g.select(mapName).select(alias).as(alias))
g
}

def setProperty[T, P](
traversal: GremlinSteps[T, P],
cypherType: CypherType,
key: String,
value: GremlinSteps[T, P]): GremlinSteps[T, P] = {
cypherType match {
case _: NodeType => traversal.property(single, key, value)
case _: RelationshipType => traversal.property(key, value)
case _ => throw new UnsupportedOperationException(s"Unsupported property type: $cypherType")
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import org.opencypher.gremlin.translation.walker.NodeUtils.notNull
import org.opencypher.v9_0.ast._
import org.opencypher.v9_0.expressions._
import org.opencypher.v9_0.util.InputPosition
import org.opencypher.v9_0.util.symbols.{AnyType, CypherType}

/**
* AST walker that handles translation
Expand Down Expand Up @@ -50,16 +51,16 @@ private class SetWalker[T, P](context: WalkerContext[T, P], g: GremlinSteps[T, P
private def walkSetClause(items: Seq[SetItem]): Unit = {
val p = context.dsl.predicates()
items.foreach {
case SetPropertyItem(Property(Variable(variable), PropertyKeyName(key)), expression: Expression) =>
setProperty(variable, key, expression)
case SetIncludingPropertiesFromMapItem(Variable(variable), MapExpression(pairs)) =>
case SetPropertyItem(Property(v @ Variable(variable), PropertyKeyName(key)), expression: Expression) =>
setProperty(typeOf(v), variable, key, expression)
case SetIncludingPropertiesFromMapItem(v @ Variable(variable), MapExpression(pairs)) =>
pairs.foreach {
case (PropertyKeyName(key), expression) => setProperty(variable, key, expression)
case (PropertyKeyName(key), expression) => setProperty(typeOf(v), variable, key, expression)
}
case SetExactPropertiesFromMapItem(Variable(variable), MapExpression(pairs)) =>
case SetExactPropertiesFromMapItem(v @ Variable(variable), MapExpression(pairs)) =>
g.select(variable).sideEffect(g.start().is(p.neq(NULL)).properties().drop())
pairs.foreach {
case (PropertyKeyName(key), expression) => setProperty(variable, key, expression)
case (PropertyKeyName(key), expression) => setProperty(typeOf(v), variable, key, expression)
}
case n =>
context.unsupported("set clause", n)
Expand All @@ -68,15 +69,19 @@ private class SetWalker[T, P](context: WalkerContext[T, P], g: GremlinSteps[T, P

private def walkRemoveClause(items: Seq[RemoveItem]): Unit = {
items.foreach {
case RemovePropertyItem(Property(Variable(variable), PropertyKeyName(key))) =>
setProperty(variable, key, Null()(InputPosition.NONE))
case RemovePropertyItem(Property(v @ Variable(variable), PropertyKeyName(key))) =>
setProperty(typeOf(v), variable, key, Null()(InputPosition.NONE))
case n =>
context.unsupported("set clause", n)
}
}

private def setProperty(variable: String, key: String, value: Expression): Unit = {
val traversal = ExpressionWalker.walkProperty(context, g.start(), key, value)
private def setProperty(cypherType: CypherType, variable: String, key: String, value: Expression): Unit = {
val traversal = ExpressionWalker.walkProperty(context, g.start(), cypherType, key, value)
g.select(variable).flatMap(notNull(traversal, context))
}

private def typeOf(expr: Expression): CypherType = {
context.expressionTypes.getOrElse(expr, AnyType.instance)
}
}
Loading

0 comments on commit 83cb6ff

Please sign in to comment.