Skip to content

Commit 92bd28b

Browse files
authored
Merge pull request #816 from s1ck/initquery_createparser
Replace Neo4jGraphFactory with CreateGraphFactory
2 parents 60bc4f1 + 3b58628 commit 92bd28b

File tree

8 files changed

+62
-128
lines changed

8 files changed

+62
-128
lines changed

okapi-neo4j-io-testing/build.gradle

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,7 @@ dependencies {
55
compile project(':okapi-neo4j-io')
66
compile project(':okapi-testing')
77

8-
compile group: 'org.neo4j.test', name: 'neo4j-harness', version: ver.neo4j.main
8+
compile group: 'org.neo4j.test', name: 'neo4j-harness', version: ver.neo4j.main
9+
compile group: 'org.neo4j.test', name: 'neo4j-harness-enterprise', version: ver.neo4j.main
10+
compile group: 'org.bouncycastle', name: 'bctls-jdk15on', version: ver.bctls
911
}

okapi-tck/src/main/scala/org/opencypher/okapi/tck/test/TCKFixture.scala

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,7 @@ import org.opencypher.okapi.api.value.CypherValue.{CypherDate => OKAPICypherDate
3636
import org.opencypher.okapi.impl.exception.NotImplementedException
3737
import org.opencypher.okapi.ir.impl.typer.exception.TypingException
3838
import org.opencypher.okapi.tck.test.TCKFixture._
39-
import org.opencypher.okapi.tck.test.support.creation.neo4j.Neo4JGraphFactory
40-
import org.opencypher.okapi.testing.propertygraph.CypherTestGraphFactory
39+
import org.opencypher.okapi.testing.propertygraph.{CreateGraphFactory, CypherTestGraphFactory}
4140
import org.opencypher.tools.tck.api._
4241
import org.opencypher.tools.tck.constants.{TCKErrorDetails, TCKErrorPhases, TCKErrorTypes}
4342
import org.opencypher.tools.tck.values.{CypherValue => TCKCypherValue, _}
@@ -85,7 +84,7 @@ case class TCKGraph[C <: CypherSession](testGraphFactory: CypherTestGraphFactory
8584
override def execute(query: String, params: Map[String, TCKCypherValue], queryType: QueryType): (Graph, Result) = {
8685
queryType match {
8786
case InitQuery =>
88-
val propertyGraph = testGraphFactory(Neo4JGraphFactory(query, params.mapValues(tckValueToCypherValue)))
87+
val propertyGraph = testGraphFactory(CreateGraphFactory(query, params.mapValues(tckValueToCypherValue)))
8988
copy(graph = propertyGraph) -> CypherValueRecords.empty
9089
case SideEffectQuery =>
9190
// this one is tricky, not sure how can do it without Cypher

okapi-tck/src/main/scala/org/opencypher/okapi/tck/test/support/creation/neo4j/Neo4JGraphFactory.scala

Lines changed: 0 additions & 110 deletions
This file was deleted.

okapi-testing/build.gradle

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@ dependencies {
55
compile project(':okapi-api')
66

77
compile group: 'org.opencypher', name: 'front-end-9.0', version: ver.cypher.frontend
8-
compile group: 'org.neo4j.test', name: 'neo4j-harness-enterprise', version: ver.neo4j.main
9-
compile group: 'org.bouncycastle', name: 'bctls-jdk15on', version: ver.bctls
108
compile group: 'junit', name: 'junit', version: ver.junit.main
119
compile group: 'org.mockito', name: 'mockito-all', version: ver.mockito
1210
compile group: 'org.scalatest', name: "scalatest".scala(), version: ver.scalatest

okapi-testing/src/main/scala/org/opencypher/okapi/testing/propertygraph/CreateQueryParser.scala

Lines changed: 47 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import cats.instances.list._
3535
import cats.syntax.all._
3636
import org.opencypher.okapi.api.value.CypherValue.{CypherEntity, CypherMap, CypherNode, CypherRelationship}
3737
import org.opencypher.okapi.impl.exception.{IllegalArgumentException, UnsupportedOperationException}
38+
import org.opencypher.okapi.impl.temporal.TemporalTypesHelper.parseDate
3839
import org.opencypher.okapi.impl.temporal.{Duration, TemporalTypesHelper}
3940
import org.opencypher.v9_0.ast._
4041
import org.opencypher.v9_0.ast.semantics.{SemanticErrorDef, SemanticState}
@@ -111,7 +112,10 @@ object CreateGraphFactory extends InMemoryGraphFactory {
111112
case head :: tail =>
112113
head match {
113114
case Create(pattern) =>
114-
processPattern(pattern) >> processClauses(tail)
115+
processPattern(pattern, merge = false) >> processClauses(tail)
116+
117+
case Merge(pattern, _, _) =>
118+
processPattern(pattern, merge = true) >> processClauses(tail)
115119

116120
case Unwind(expr, variable) =>
117121
for {
@@ -133,16 +137,16 @@ object CreateGraphFactory extends InMemoryGraphFactory {
133137
}
134138
}
135139

136-
def processPattern(pattern: Pattern): Result[Unit] = {
140+
def processPattern(pattern: Pattern, merge: Boolean): Result[Unit] = {
137141
val parts = pattern.patternParts.map {
138142
case EveryPath(element) => element
139143
case other => throw UnsupportedOperationException(s"Processing pattern: ${other.getClass.getSimpleName}")
140144
}
141145

142-
Foldable[List].sequence_[Result, CypherEntity[Long]](parts.toList.map(pe => processPatternElement(pe)))
146+
Foldable[List].sequence_[Result, CypherEntity[Long]](parts.toList.map(pe => processPatternElement(pe, merge)))
143147
}
144148

145-
def processPatternElement(patternElement: ASTNode): Result[CypherEntity[Long]] = {
149+
def processPatternElement(patternElement: ASTNode, merge: Boolean): Result[CypherEntity[Long]] = {
146150
patternElement match {
147151
case NodePattern(Some(variable), labels, props, _) =>
148152
for {
@@ -160,7 +164,7 @@ object CreateGraphFactory extends InMemoryGraphFactory {
160164
}
161165
_ <- modify[ParsingContext] { context =>
162166
if (context.variableMapping.get(variable.name).isEmpty) {
163-
context.updated(variable.name, node)
167+
context.updated(variable.name, node, merge)
164168
} else {
165169
context
166170
}
@@ -169,12 +173,12 @@ object CreateGraphFactory extends InMemoryGraphFactory {
169173

170174
case RelationshipChain(first, RelationshipPattern(Some(variable), relType, None, props, direction, _, _), third) =>
171175
for {
172-
source <- processPatternElement(first)
176+
source <- processPatternElement(first, merge)
173177
sourceId <- pure[ParsingContext, Long](source match {
174178
case n: CypherNode[Long] => n.id
175179
case r: CypherRelationship[Long] => r.endId
176180
})
177-
target <- processPatternElement(third)
181+
target <- processPatternElement(third, merge)
178182
properties <- props match {
179183
case Some(expr: MapExpression) => extractProperties(expr)
180184
case Some(other) => throw IllegalArgumentException("a RelationshipChain with MapExpression", other)
@@ -214,15 +218,41 @@ object CreateGraphFactory extends InMemoryGraphFactory {
214218

215219
case ListLiteral(expressions) => expressions.toList.traverse[Result, Any](processExpr)
216220

221+
case Modulo(lhs, rhs) =>
222+
for {
223+
leftVal <- processExpr(lhs)
224+
rightVal <- processExpr(rhs)
225+
res <- pure[ParsingContext, Any](leftVal.asInstanceOf[Long] % rightVal.asInstanceOf[Long])
226+
} yield res
227+
228+
case MapExpression(items) =>
229+
for {
230+
keys <- pure(items.map { case (k, _) => k.name })
231+
valueTypes <- items.toList.traverse[Result, Any] { case (_, v) => processExpr(v) }
232+
res <- pure[ParsingContext, Any](keys.zip(valueTypes).toMap)
233+
} yield res
234+
217235
case FunctionInvocation(_, FunctionName("date"), _, Seq(dateString: StringLiteral)) =>
218-
pure[ParsingContext, Any](TemporalTypesHelper.parseDate(Right(dateString.value)))
236+
pure[ParsingContext, Any](parseDate(Right(dateString.value)))
237+
238+
case FunctionInvocation(_, FunctionName("date"), _, Seq(map: MapExpression)) =>
239+
for {
240+
dateMap <- processExpr(map)
241+
res <- pure[ParsingContext, Any](parseDate(Left(dateMap.asInstanceOf[Map[String, Long]].mapValues(_.toInt))))
242+
} yield res
219243

220244
case FunctionInvocation(_, FunctionName("localdatetime"), _, Seq(dateString: StringLiteral)) =>
221245
pure[ParsingContext, Any](TemporalTypesHelper.parseLocalDateTime(Right(dateString.value)))
222246

223247
case FunctionInvocation(_, FunctionName("duration"), _, Seq(dateString: StringLiteral)) =>
224248
pure[ParsingContext, Any](Duration.parse(dateString.value))
225249

250+
case FunctionInvocation(_, FunctionName("duration"), _, Seq(map: MapExpression)) =>
251+
for {
252+
durationMap <- processExpr(map)
253+
res <- pure[ParsingContext, Any](Duration(durationMap.asInstanceOf[Map[String, Long]]))
254+
} yield res
255+
226256
case Property(variable: Variable, propertyKey) =>
227257
inspect[ParsingContext, Any]({ context =>
228258
context.variableMapping(variable.name) match {
@@ -280,16 +310,22 @@ final case class ParsingContext(
280310

281311
def popProtectedScope: ParsingContext = copy(protectedScopes = protectedScopes.tail)
282312

283-
def updated(k: String, v: Any): ParsingContext = v match {
284-
case n: InMemoryTestNode =>
313+
def updated(k: String, v: Any, merge: Boolean = false): ParsingContext = v match {
314+
case n: InMemoryTestNode if !merge || !containsNode(n) =>
285315
copy(graph = graph.updated(n), variableMapping = variableMapping.updated(k, n))
286316

287-
case r: InMemoryTestRelationship =>
317+
case r: InMemoryTestRelationship if !merge || !containsRel(r) =>
288318
copy(graph = graph.updated(r), variableMapping = variableMapping.updated(k, r))
289319

290320
case _ =>
291321
copy(variableMapping = variableMapping.updated(k, v))
292322
}
323+
324+
private def containsNode(n: InMemoryTestNode): Boolean =
325+
graph.nodes.exists(n.equalsSemantically)
326+
327+
private def containsRel(r: InMemoryTestRelationship): Boolean =
328+
graph.relationships.exists(r.equalsSemantically)
293329
}
294330

295331
object ParsingContext {

okapi-testing/src/main/scala/org/opencypher/okapi/testing/propertygraph/InMemoryTestGraph.scala

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@ case class InMemoryTestNode(
6666
override def copy(id: Long = id, labels: Set[String] = labels, properties: CypherMap = properties): InMemoryTestNode.this.type = {
6767
InMemoryTestNode(id, labels, properties).asInstanceOf[this.type]
6868
}
69+
70+
def equalsSemantically(other: I): Boolean = {
71+
this.labels == other.labels && this.properties == other.properties
72+
}
6973
}
7074

7175
case class InMemoryTestRelationship(
@@ -82,6 +86,10 @@ case class InMemoryTestRelationship(
8286
InMemoryTestRelationship(id, source, target, relType, properties).asInstanceOf[this.type]
8387
}
8488

89+
def equalsSemantically(other: I): Boolean = {
90+
this.relType == other.relType && this.properties == other.properties
91+
}
92+
8593
}
8694

8795
trait InMemoryGraphFactory {

spark-cypher-tck/src/test/resources/temporal_blacklist

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ Feature "TemporalCreateAcceptance": Scenario "Should construct date time with de
8383
Feature "TemporalArithmeticAcceptance": Scenario "Should add or subtract duration to or from local time #1"
8484
Feature "TemporalArithmeticAcceptance": Scenario "Should add or subtract duration to or from local time #2"
8585
Feature "TemporalArithmeticAcceptance": Scenario "Should add or subtract duration to or from local time #3"
86+
Feature "TemporalArithmeticAcceptance": Scenario "Should add or subtract duration to or from date #3"
8687
Feature "TemporalParseAcceptance": Scenario "Should parse date time with named time zone from string #1"
8788
Feature "TemporalParseAcceptance": Scenario "Should parse date time with named time zone from string #2"
8889
Feature "TemporalParseAcceptance": Scenario "Should parse date time with named time zone from string #3"

spark-cypher-tck/src/test/scala/org/opencypher/spark/testing/TckSparkCypherTest.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ class TckSparkCypherTest extends CAPSTestSuite {
128128
}
129129

130130
ignore("run custom scenario") {
131-
val file = new File(getClass.getResource("CustomTest.feature").toURI)
131+
val file = new File(getClass.getResource("/CustomTest.feature").toURI)
132132

133133
CypherTCK
134134
.parseFilesystemFeature(file)

0 commit comments

Comments
 (0)