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

Implement EXTENDS syntax for Graph DDL #787

Merged
merged 13 commits into from
Feb 6, 2019

Conversation

s1ck
Copy link
Contributor

@s1ck s1ck commented Feb 5, 2019

This introduces EXTENDS syntax as in the following example:

A ( a STRING ),
B ( b STRING ),
C EXTENDS A ( c STRING ),
D EXTENDS A, B ( d STRING ),

(A), -- resolves to LabelSet (A)
(B), -- resolves to LabelSet (B)
(C), -- resolves to LabelSet (A, C)
(D), -- resolves to LabelSet (A, B, D)

We still support the previous syntax, e.g. given the above element types it is valid to write:

(A, B), -- resolves to LabelSet (A, B)
(C, D), -- resolves to LabelSet (A, B, C, D)

@jjaderberg
Copy link
Contributor

Quick turnaround on that one!

@DarthMax DarthMax self-assigned this Feb 6, 2019
Copy link
Contributor

@DarthMax DarthMax left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM


def elementTypeDefinition[_: P]: P[ElementTypeDefinition] =
P(identifier.! ~/ extendsDefinition.?.map(_.getOrElse(Set.empty)) ~/ properties.?.map(_.getOrElse(Map.empty)) ~/ keyDefinition.?).map {
case (id, parents, props, maybeKey) => ElementTypeDefinition(id, parents, props, maybeKey)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we could move the map(_.getOrElse(???)) stuff inside the case in order to make the parser it self more easily readable

GraphDdl(ddl).graphs(graphName).graphType should equal(
Schema.empty
.withNodePropertyKeys("A")("foo" -> CTString)
.withNodePropertyKeys("A", "B")("foo" -> CTString, "bar" -> CTString)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seeing both definitions side by side the result is rather surprising.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How do you mean?

}
resolved.head.name
}

private def mergeProperties(elementTypes: Set[ElementTypeDefinition]): PropertyKeys = {
elementTypes
.flatMap(_.properties)
.foldLeft(PropertyKeys.empty) { case (props, (name, cypherType)) =>
props.get(name).filter(_ != cypherType) match {
case Some(t) => incompatibleTypes(name, cypherType, t)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Side note:
Why do we throw an error here? Shouldn't Cypher generally support this. It is more a spark-cypher restriction

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exactly! I thought the same and will change it in another PR and do the error handling in SQL PGDS (just didn't want to touch it in this PR)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

)
)

it("allows compact inline graph definition with complex node type") {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we add a test for conflicting property types, e.g.

A (y String)
B (y Integer)
C EXTENDS A, B

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has been tested before for the non-extends variant. However, I added an additional test.

private def resolveParents(node: ElementTypeDefinition): Set[ElementTypeDefinition] =
node.parents.map(resolveElementType).flatMap(resolveParents) + node

private def detectCircularDependency(node: ElementTypeDefinition): Unit = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 😉

@s1ck s1ck merged commit 8b70d4b into opencypher:master Feb 6, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants