Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor pattern conversion #923

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
package org.opencypher.okapi.api.graph

import org.opencypher.okapi.api.graph.Pattern._
import org.opencypher.okapi.api.types.{CTNode, CTRelationship, CypherType}

sealed trait Direction
case object Outgoing extends Direction
Expand All @@ -37,16 +36,18 @@ case object Both extends Direction
case class Connection(
source: Option[PatternElement],
target: Option[PatternElement],
direction: Direction
direction: Direction,
lower: Int = 1,
upper: Int = 1
)

/**
* Represents an element within a pattern, e.g. a node or a relationship
*
* @param name the elements name
* @param cypherType the elements CypherType
*/
case class PatternElement(name: String, cypherType: CypherType)
sealed trait PatternElement {
def name: String
def labels: Set[String]
}

case class NodeElement(name: String)(override val labels: Set[String]) extends PatternElement
case class RelationshipElement(name: String)(override val labels: Set[String]) extends PatternElement

object Pattern {
val DEFAULT_NODE_NAME = "node"
Expand Down Expand Up @@ -78,7 +79,7 @@ sealed trait Pattern {
*
* @return the patterns topology
*/
def topology: Map[PatternElement, Connection]
def topology: Map[String, Connection]

//TODO: to support general patterns implement a pattern matching algorithm
/**
Expand Down Expand Up @@ -132,34 +133,34 @@ sealed trait Pattern {
def superTypeOf(other: Pattern): Boolean = other.subTypeOf(this)
}

case class NodePattern(nodeType: CTNode) extends Pattern {
val nodeElement = PatternElement(DEFAULT_NODE_NAME, nodeType)
case class NodePattern(nodeLabels: Set[String]) extends Pattern {
val nodeElement = NodeElement(DEFAULT_NODE_NAME)(nodeLabels)

override def elements: Set[PatternElement] = Set(nodeElement)
override def topology: Map[PatternElement, Connection] = Map.empty
override def topology: Map[String, Connection] = Map.empty

override def subTypeOf(other: Pattern): Boolean = other match {
case NodePattern(otherNodeType) => nodeType.withoutGraph.subTypeOf(otherNodeType.withoutGraph)
case NodePattern(otherNodeLabels) => nodeLabels.subsetOf(otherNodeLabels) || otherNodeLabels.isEmpty
case _ => false
}
}

case class RelationshipPattern(relType: CTRelationship) extends Pattern {
val relElement = PatternElement(DEFAULT_REL_NAME, relType)
case class RelationshipPattern(relTypes: Set[String]) extends Pattern {
val relElement = RelationshipElement(DEFAULT_REL_NAME)(relTypes)

override def elements: Set[PatternElement] = Set(relElement)
override def topology: Map[PatternElement, Connection] = Map.empty
override def topology: Map[String, Connection] = Map.empty

override def subTypeOf(other: Pattern): Boolean = other match {
case RelationshipPattern(otherRelType) => relType.withoutGraph.subTypeOf(otherRelType.withoutGraph)
case RelationshipPattern(otherRelTypes) => relTypes.subsetOf(otherRelTypes) || otherRelTypes.isEmpty
case _ => false
}
}

case class NodeRelPattern(nodeType: CTNode, relType: CTRelationship) extends Pattern {
case class NodeRelPattern(nodeLabels: Set[String], relTypes: Set[String]) extends Pattern {

val nodeElement = PatternElement(DEFAULT_NODE_NAME, nodeType)
val relElement = PatternElement(DEFAULT_REL_NAME, relType)
val nodeElement = NodeElement(DEFAULT_NODE_NAME)(nodeLabels)
val relElement = RelationshipElement(DEFAULT_REL_NAME)(relTypes)

override def elements: Set[PatternElement] = {
Set(
Expand All @@ -168,37 +169,36 @@ case class NodeRelPattern(nodeType: CTNode, relType: CTRelationship) extends Pat
)
}

override def topology: Map[PatternElement, Connection] = Map(
relElement -> Connection(Some(nodeElement), None, Outgoing)
override def topology: Map[String, Connection] = Map(
relElement.name -> Connection(Some(nodeElement), None, Outgoing)
)

override def subTypeOf(other: Pattern): Boolean = other match {
case NodeRelPattern(otherNodeType, otherRelType) =>
nodeType.withoutGraph.subTypeOf(otherNodeType.withoutGraph) && relType.withoutGraph.subTypeOf(otherRelType.withoutGraph)
case NodeRelPattern(otherNodeLabels, otherRelTypes) => (nodeLabels.subsetOf(otherNodeLabels) || otherNodeLabels.isEmpty) && (relTypes.subsetOf(otherRelTypes) || otherRelTypes.isEmpty)
case _ => false
}
}

case class TripletPattern(sourceNodeType: CTNode, relType: CTRelationship, targetNodeType: CTNode) extends Pattern {
val sourceElement = PatternElement("source_" + DEFAULT_NODE_NAME, sourceNodeType)
val targetElement = PatternElement("target_" + DEFAULT_NODE_NAME, targetNodeType)
val relElement = PatternElement(DEFAULT_REL_NAME, relType)
case class TripletPattern(sourceNodeLabels: Set[String], relTypes: Set[String], targetNodeLabels: Set[String]) extends Pattern {
val sourceElement = NodeElement("source_" + DEFAULT_NODE_NAME)(sourceNodeLabels)
val targetElement = NodeElement("target_" + DEFAULT_NODE_NAME)(targetNodeLabels)
val relElement = RelationshipElement(DEFAULT_REL_NAME)(relTypes)

override def elements: Set[PatternElement] = Set(
sourceElement,
relElement,
targetElement
)

override def topology: Map[PatternElement, Connection] = Map(
relElement -> Connection(Some(sourceElement), Some(targetElement), Outgoing)
override def topology: Map[String, Connection] = Map(
relElement.name -> Connection(Some(sourceElement), Some(targetElement), Outgoing)
)

override def subTypeOf(other: Pattern): Boolean = other match {
case tr: TripletPattern =>
sourceNodeType.withoutGraph.subTypeOf(tr.sourceNodeType.withoutGraph) &&
relType.withoutGraph.subTypeOf(tr.relType.withoutGraph) &&
targetNodeType.withoutGraph.subTypeOf(tr.targetNodeType.withoutGraph)
(sourceNodeLabels.subsetOf(tr.sourceNodeLabels) || tr.sourceNodeLabels.isEmpty) &&
(relTypes.subsetOf(tr.relTypes) || tr.relTypes.isEmpty) &&
(targetNodeLabels.subsetOf(tr.targetNodeLabels) || tr.targetNodeLabels.isEmpty)
case _ => false
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,6 @@ trait PropertyGraph {
* @return patterns that the graph can provide
*/
def patterns: Set[Pattern] =
schema.labelCombinations.combos.map(c => NodePattern(CTNode(c))) ++
schema.relationshipTypes.map(r => RelationshipPattern(CTRelationship(r)))
schema.labelCombinations.combos.map(c => NodePattern(c)) ++
schema.relationshipTypes.map(r => RelationshipPattern(Set(r)))
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@
*/
package org.opencypher.okapi.api.io.conversion

import org.opencypher.okapi.api.graph.{PatternElement, IdKey, Pattern}
import org.opencypher.okapi.api.types.CTRelationship
import org.opencypher.okapi.api.graph.{IdKey, Pattern, PatternElement, RelationshipElement}
import org.opencypher.okapi.impl.exception.IllegalArgumentException

object ElementMapping {
Expand Down Expand Up @@ -74,7 +73,7 @@ case class ElementMapping(
}

pattern.elements.foreach {
case e@PatternElement(_, CTRelationship(types, _)) if types.size != 1 =>
case e@RelationshipElement(_, types) if types.size != 1 =>
throw IllegalArgumentException(
s"A single implied type for element $e",
types
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
package org.opencypher.okapi.api.io.conversion

import org.opencypher.okapi.api.graph._
import org.opencypher.okapi.api.types.CTNode

object NodeMappingBuilder {
/**
Expand Down Expand Up @@ -113,7 +112,7 @@ final case class NodeMappingBuilder(
copy(propertyMapping = updatedPropertyMapping)

override def build: ElementMapping = {
val pattern: NodePattern = NodePattern(CTNode(impliedNodeLabels))
val pattern: NodePattern = NodePattern(impliedNodeLabels)
val properties: Map[PatternElement, Map[String, String]] = Map(pattern.nodeElement -> propertyMapping)
val idKeys: Map[PatternElement, Map[IdKey, String]] = Map(pattern.nodeElement -> Map(SourceIdKey -> nodeIdKey))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
package org.opencypher.okapi.api.io.conversion

import org.opencypher.okapi.api.graph._
import org.opencypher.okapi.api.types.CTRelationship
import org.opencypher.okapi.impl.exception.IllegalArgumentException

object RelationshipMappingBuilder {
Expand Down Expand Up @@ -171,7 +170,7 @@ final case class RelationshipMappingBuilder(
override def build: ElementMapping = {
validate()

val pattern: RelationshipPattern = RelationshipPattern(CTRelationship(relType))
val pattern: RelationshipPattern = RelationshipPattern(Set(relType))

val properties: Map[PatternElement, Map[String, String]] = Map(pattern.relElement -> propertyMapping)
val idKeys: Map[PatternElement, Map[IdKey, String]] = Map(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,9 @@ import org.opencypher.okapi.ir.api.pattern.Pattern

final case class MatchBlock(
after: List[Block],
binds: Pattern,
binds: Fields,
pattern: Pattern,
where: Set[Expr] = Set.empty[Expr],
optional: Boolean,
graph: IRGraph
) extends BasicBlock[Pattern](BlockType("match"))
) extends BasicBlock[Fields](BlockType("match"))
Loading