Skip to content

Commit 0f89393

Browse files
DirkMahlerDirk MahlerAndy2003
authored
Added alias or field name as variable to Cypher.kt (#172)
* append operand name in filter expressions * added alias or fieldname as variable to Cypher.kt * use variable everywhere Co-authored-by: Dirk Mahler <dirk.mahler@asml.com> Co-authored-by: Andreas Berger <andreas@berger-ecommerce.com>
1 parent 2021d1a commit 0f89393

File tree

9 files changed

+25
-35
lines changed

9 files changed

+25
-35
lines changed

core/src/main/kotlin/org/neo4j/graphql/Cypher.kt

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,7 @@ package org.neo4j.graphql
22

33
import graphql.schema.GraphQLType
44

5-
data class Cypher @JvmOverloads constructor(val query: String, val params: Map<String, Any?> = emptyMap(), var type: GraphQLType? = null) {
5+
data class Cypher @JvmOverloads constructor(val query: String, val params: Map<String, Any?> = emptyMap(), var type: GraphQLType? = null, val variable: String) {
66
fun with(p: Map<String, Any?>) = this.copy(params = this.params + p)
77
fun escapedQuery() = query.replace("\"", "\\\"").replace("'", "\\'")
8-
9-
companion object {
10-
@JvmStatic
11-
val EMPTY = Cypher("")
12-
}
13-
}
8+
}

core/src/main/kotlin/org/neo4j/graphql/GraphQLExtensions.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -200,8 +200,7 @@ fun <T> GraphQLDirective.getArgument(argumentName: String, defaultValue: T? = nu
200200
?: throw IllegalStateException("No default value for @${this.name}::$argumentName")
201201
}
202202

203-
fun GraphQLFieldDefinition.cypherDirective(): Cypher? = getDirectiveArgument<String>(CYPHER, CYPHER_STATEMENT, null)
204-
?.let { statement -> Cypher(statement) }
203+
fun GraphQLFieldDefinition.cypherDirective(): String? = getDirectiveArgument<String>(CYPHER, CYPHER_STATEMENT, null)
205204

206205
fun Any.toJavaValue() = when (this) {
207206
is Value<*> -> this.toJavaValue()

core/src/main/kotlin/org/neo4j/graphql/handler/BaseDataFetcher.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ abstract class BaseDataFetcher(val fieldDefinition: GraphQLFieldDefinition) : Pr
2929
.withPrettyPrint(true)
3030
.build()
3131
).render(statement)
32-
return Cypher(query, statement.parameters, fieldDefinition.type)
32+
return Cypher(query, statement.parameters, fieldDefinition.type, variable = variable)
3333
}
3434

3535
protected abstract fun generateCypher(variable: String, field: Field, env: DataFetchingEnvironment): Statement

core/src/main/kotlin/org/neo4j/graphql/handler/CypherDirectiveHandler.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import org.neo4j.graphql.*
1515
class CypherDirectiveHandler(
1616
private val type: GraphQLFieldsContainer?,
1717
private val isQuery: Boolean,
18-
private val cypherDirective: Cypher,
18+
private val cypherDirective: String,
1919
fieldDefinition: GraphQLFieldDefinition)
2020
: BaseDataFetcher(fieldDefinition) {
2121

core/src/main/kotlin/org/neo4j/graphql/handler/projection/ProjectionBase.kt

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import org.neo4j.cypherdsl.core.Node
1010
import org.neo4j.cypherdsl.core.StatementBuilder.TerminalExposesLimit
1111
import org.neo4j.cypherdsl.core.StatementBuilder.TerminalExposesSkip
1212
import org.neo4j.graphql.*
13-
import org.neo4j.graphql.Cypher
1413
import org.neo4j.graphql.parser.ParsedQuery
1514
import org.neo4j.graphql.parser.QueryParser.parseArguments
1615
import org.neo4j.graphql.parser.QueryParser.parseFilter
@@ -276,13 +275,13 @@ open class ProjectionBase {
276275
return mapOf(*projections.toTypedArray())
277276
}
278277

279-
fun cypherDirective(variable: String, fieldDefinition: GraphQLFieldDefinition, field: Field, cypherDirective: Cypher, thisValue: Any? = null): Expression {
278+
fun cypherDirective(variable: String, fieldDefinition: GraphQLFieldDefinition, field: Field, cypherDirective: String, thisValue: Any? = null): Expression {
280279
val suffix = if (fieldDefinition.type.isList()) "Many" else "Single"
281280
val args = cypherDirectiveQuery(variable, fieldDefinition, field, cypherDirective, thisValue)
282281
return call("apoc.cypher.runFirstColumn$suffix").withArgs(*args).asFunction()
283282
}
284283

285-
fun cypherDirectiveQuery(variable: String, fieldDefinition: GraphQLFieldDefinition, field: Field, cypherDirective: Cypher, thisValue: Any? = null): Array<Expression> {
284+
fun cypherDirectiveQuery(variable: String, fieldDefinition: GraphQLFieldDefinition, field: Field, cypherDirective: String, thisValue: Any? = null): Array<Expression> {
286285
val args = mutableMapOf<String, Any?>()
287286
if (thisValue != null) args["this"] = thisValue
288287
field.arguments.forEach { args[it.name] = it.value }
@@ -291,7 +290,7 @@ open class ProjectionBase {
291290
.forEach { args[it.name] = it.defaultValue }
292291

293292
val argParams = args.map { (name, _) -> "$$name AS $name" }.joinNonEmpty(", ")
294-
val query = (if (argParams.isEmpty()) "" else "WITH $argParams ") + cypherDirective.query
293+
val query = (if (argParams.isEmpty()) "" else "WITH $argParams ") + cypherDirective
295294
val argExpressions = args.flatMap { (name, value) -> listOf(name, if (name == "this") value else queryParameter(value, variable, name)) }
296295
return arrayOf(literalOf<String>(query), mapOf(*argExpressions.toTypedArray()))
297296
}

core/src/test/kotlin/DataFetcherInterceptorDemo.kt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,11 @@ fun initBoundSchema(schema: String): GraphQLSchema {
2121
val cypher = delegate.get(env)
2222
return driver.session().use { session ->
2323
val result = session.run(cypher.query, cypher.params.mapValues { toBoltValue(it.value, env.variables) })
24-
val key = result.keys().stream().findFirst().orElse(null)
2524
if (isListType(cypher.type)) {
26-
result.list().map { record -> record.get(key).asObject() }
25+
result.list().map { record -> record.get(cypher.variable).asObject() }
2726

2827
} else {
29-
result.list().map { record -> record.get(key).asObject() }
28+
result.list().map { record -> record.get(cypher.variable).asObject() }
3029
.firstOrNull() ?: emptyMap<String, Any>()
3130
}
3231
}

core/src/test/kotlin/GraphQLServer.kt

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import org.neo4j.graphql.*
1414
import spark.Request
1515
import spark.Response
1616
import spark.Spark
17+
import java.util.*
1718

1819
const val schema = """
1920
type Person {
@@ -63,11 +64,13 @@ fun main() {
6364
try {
6465
// todo fix parameter mapping in translator
6566
val result = it.run(cypher.query, Values.value(cypher.params))
66-
if (cypher.type?.isList() == true) {
67-
result.keys().map { key -> key to result.list().map { row -> row.get(key).asObject() } }.toMap(LinkedHashMap())
67+
val value = if (cypher.type?.isList() == true) {
68+
result.list().map { row -> row.get(cypher.variable).asObject() }
6869
} else {
69-
result.keys().map { key -> key to result.list().map { row -> row.get(key).asObject() }.firstOrNull() }.toMap(LinkedHashMap())
70+
result.list().map { record -> record.get(cypher.variable).asObject() }
71+
.firstOrNull() ?: emptyMap<String, Any>()
7072
}
73+
Collections.singletonMap(cypher.variable, value)
7174
} catch (e: Exception) {
7275
e.printStackTrace()
7376
}

core/src/test/kotlin/org/neo4j/graphql/utils/CypherTestSuite.kt

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -154,19 +154,15 @@ class CypherTestSuite(fileName: String) : AsciiDocTestSuite(
154154
.forEach { server.graph().execute(it) }
155155
}
156156

157-
val (cypher, params, type) = result()
157+
val (cypher, params, type, variable) = result()
158158
val dbResult = server.graph().execute(cypher, params)
159159

160-
val values = dbResult.columns().map { key ->
161-
key to dbResult.stream()
162-
.map { it[key] }
163-
.let {
164-
when {
165-
type?.isList() == true -> it.toList()
166-
else -> it.findFirst().orElse(null)
167-
}
168-
}
169-
}.toMap(LinkedHashMap())
160+
val values = mutableMapOf(variable to dbResult.stream().map { it[variable] }.let {
161+
when {
162+
type?.isList() == true -> it.toList()
163+
else -> it.findFirst().orElse(null)
164+
}
165+
})
170166

171167
if (response.code.isEmpty()) {
172168
val actualCode = MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(values)

examples/graphql-spring-boot/src/main/kotlin/org/neo4j/graphql/examples/graphqlspringboot/config/Neo4jConfiguration.kt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,12 @@ open class Neo4jConfiguration {
3030
return driver.session().writeTransaction { tx ->
3131
val boltParams = cypher.params.mapValues { toBoltValue(it.value, env.variables) }
3232
val result = tx.run(cypher.query, boltParams)
33-
val key = result.keys().stream().findFirst().orElse(null)
3433
if (isListType(cypher.type)) {
3534
result.list()
36-
.map { record -> record.get(key).asObject() }
35+
.map { record -> record.get(cypher.variable).asObject() }
3736
} else {
3837
result.list()
39-
.map { record -> record.get(key).asObject() }
38+
.map { record -> record.get(cypher.variable).asObject() }
4039
.firstOrNull() ?: emptyMap<String, Any>()
4140
}
4241
}

0 commit comments

Comments
 (0)